如何在WPF中停止线程

 我来答
福喜900
推荐于2016-03-19 · TA获得超过6.1万个赞
知道大有可为答主
回答量:1.1万
采纳率:0%
帮助的人:1亿
展开全部
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只是临时停止,还会再用到,那么使用信号控制就可以了。
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式