如何在WPF中停止线程
展开全部
1. Abort的非及时性
使用多线程经常会遇到一个问题,如何停止这个Thread?在WPF中提供了Abort方法,但MSDN却告诉我们:
线程不一定会立即中止,或者根本不中止。 如果线程在作为中止过程的一部分被调用的 finally 块中做非常大量的计算,从而无限期延迟中止操作,则会发生这种情况。
先看下面一段代码:
public partial class MainWindow : Window
{
Thread thread;
public MainWindow()
{
InitializeComponent();
Test t = new Test();
thread = new Thread(new ThreadStart(t.Run));
thread.Start();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("abort");
thread.Abort();
}
}
public class Test
{
public void Run()
{
while (true)
{
Console.WriteLine("Running...");
}
}
}
在运行中点击Button,则可能得到的输出如下:
图1
可以看到Abort后线程仍在运行,然后才停止,输出的结果是多变的,有可能Abort之后再无输出,也有可能输出多行,但都能说明一个问题: 使用abort不能立即终止一个thread.
那么到这里,需要先认识一下究竟Abort是什么?
简单来说,Abort是一个标识或者信号,调用它会引发ThreadAbortException,Abort会去请求终止thread,但这不是立即的。
改动一下代码再看看结果:
private void Button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("abort");
thread.Abort();
Console.WriteLine(thread.IsAlive);
Console.WriteLine(thread.ThreadState);
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Console.WriteLine(thread.IsAlive);
Console.WriteLine(thread.ThreadState);
}
图2
点击Button执行Abort后立即输出thread的状态,发现 IsAlive=True , ThreadState=Running ,当然也有可能是 IsAlive=False , ThreadState=Aborted ,因为Abort是不稳定的。然后停一段时间确保thread被终止再点击Button1输出thread的状态,此时 IsAlive=False , ThreadState=Aborted .
2. Abort和Join同时使用的意义
由于abort之后获取到的thread的信息是不稳定的,所以可能会想到用Join,它的作用是:
使用此方法确保线程已终止。 如果线程不终止,则调用方将无限期阻塞。 如果调用 Join 时该线程已终止,此方法将立即返回。
也就是说如果我们使用Abort之后再加上Join,那么Join之后的thread肯定是Aborted.
修改一下Button的代码:
private void Button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("abort");
thread.Abort();
thread.Join();
Console.WriteLine(thread.IsAlive);
Console.WriteLine(thread.ThreadState);
}
没有加入Join之前,输出的IsAlive和ThreadState可能是多种情况的,加入之后,输出的一定是 IsAlive=False , ThreadState=Aborted .
需要注意的是Join的作用并不是终止thread,它只是等待thread直到thread执行完成。
3. 如何停止线程
如果考虑让一个thread先停止,然后需要的时候再执行,那么使用abort是很不明智的。一般来说只有当应用程序退出,我们才需要把thread彻底关闭,也就是这时候才用到abort。对于停止线程的需求,可以通过信号来解决:
public partial class MainWindow : Window
{
Thread thread;
Test t;
public MainWindow()
{
InitializeComponent();
t = new Test();
thread = new Thread(new ThreadStart(t.Run));
thread.Start();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
t.Flag = !t.Flag;
}
}
public class Test
{
private bool _flag;
public bool Flag
{
set
{
_flag = value;
if (_flag == true)
{
Console.WriteLine("flag=true");
}
else
{
Console.WriteLine("flag=false");
}
}
get
{
return _flag;
}
}
public void Run()
{
while (true)
{
if (Flag)
{
Console.WriteLine("Running...");
}
}
}
}
上面的例子通过信号量来控制thread中的内容是否执行,在实际应用中,如果一个thread中的内容可能再也不会用到,那么对于这一类情况,使用abort和join;如果这个thread只是临时停止,还会再用到,那么使用信号控制就可以了。
使用多线程经常会遇到一个问题,如何停止这个Thread?在WPF中提供了Abort方法,但MSDN却告诉我们:
线程不一定会立即中止,或者根本不中止。 如果线程在作为中止过程的一部分被调用的 finally 块中做非常大量的计算,从而无限期延迟中止操作,则会发生这种情况。
先看下面一段代码:
public partial class MainWindow : Window
{
Thread thread;
public MainWindow()
{
InitializeComponent();
Test t = new Test();
thread = new Thread(new ThreadStart(t.Run));
thread.Start();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("abort");
thread.Abort();
}
}
public class Test
{
public void Run()
{
while (true)
{
Console.WriteLine("Running...");
}
}
}
在运行中点击Button,则可能得到的输出如下:
图1
可以看到Abort后线程仍在运行,然后才停止,输出的结果是多变的,有可能Abort之后再无输出,也有可能输出多行,但都能说明一个问题: 使用abort不能立即终止一个thread.
那么到这里,需要先认识一下究竟Abort是什么?
简单来说,Abort是一个标识或者信号,调用它会引发ThreadAbortException,Abort会去请求终止thread,但这不是立即的。
改动一下代码再看看结果:
private void Button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("abort");
thread.Abort();
Console.WriteLine(thread.IsAlive);
Console.WriteLine(thread.ThreadState);
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Console.WriteLine(thread.IsAlive);
Console.WriteLine(thread.ThreadState);
}
图2
点击Button执行Abort后立即输出thread的状态,发现 IsAlive=True , ThreadState=Running ,当然也有可能是 IsAlive=False , ThreadState=Aborted ,因为Abort是不稳定的。然后停一段时间确保thread被终止再点击Button1输出thread的状态,此时 IsAlive=False , ThreadState=Aborted .
2. Abort和Join同时使用的意义
由于abort之后获取到的thread的信息是不稳定的,所以可能会想到用Join,它的作用是:
使用此方法确保线程已终止。 如果线程不终止,则调用方将无限期阻塞。 如果调用 Join 时该线程已终止,此方法将立即返回。
也就是说如果我们使用Abort之后再加上Join,那么Join之后的thread肯定是Aborted.
修改一下Button的代码:
private void Button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("abort");
thread.Abort();
thread.Join();
Console.WriteLine(thread.IsAlive);
Console.WriteLine(thread.ThreadState);
}
没有加入Join之前,输出的IsAlive和ThreadState可能是多种情况的,加入之后,输出的一定是 IsAlive=False , ThreadState=Aborted .
需要注意的是Join的作用并不是终止thread,它只是等待thread直到thread执行完成。
3. 如何停止线程
如果考虑让一个thread先停止,然后需要的时候再执行,那么使用abort是很不明智的。一般来说只有当应用程序退出,我们才需要把thread彻底关闭,也就是这时候才用到abort。对于停止线程的需求,可以通过信号来解决:
public partial class MainWindow : Window
{
Thread thread;
Test t;
public MainWindow()
{
InitializeComponent();
t = new Test();
thread = new Thread(new ThreadStart(t.Run));
thread.Start();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
t.Flag = !t.Flag;
}
}
public class Test
{
private bool _flag;
public bool Flag
{
set
{
_flag = value;
if (_flag == true)
{
Console.WriteLine("flag=true");
}
else
{
Console.WriteLine("flag=false");
}
}
get
{
return _flag;
}
}
public void Run()
{
while (true)
{
if (Flag)
{
Console.WriteLine("Running...");
}
}
}
}
上面的例子通过信号量来控制thread中的内容是否执行,在实际应用中,如果一个thread中的内容可能再也不会用到,那么对于这一类情况,使用abort和join;如果这个thread只是临时停止,还会再用到,那么使用信号控制就可以了。
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询