看看这个简单的课程:
delegate void Log(String message);
class A {
public Log log;
...
public void test() {
// Empty
}
}
现在我正在从主GUI线程创建并启动一个线程,并检查它是否结束。
A a = new A();
a.log += Log;
Thread t = new Thread(new ThreadStart(a.test));
t.Start();
while(true) {
System.Threading.Thread.Sleep(200);
Console.WriteLine(t.IsAlive);
}
上面的代码一切正常:
true
true
....
false
false
false
...
现在我将test
方法的代码更改为
public void test() {
log("Test");
}
GUI类中的Log
方法如下所示:
private void Log(String message)
{
if (this.tb_log.InvokeRequired)
{
this.tb_log.Invoke((MethodInvoker)delegate()
{
Log(message);
});
}
else
{
// do something with the textbox in the GUI
}
}
现在,虽然函数终止,但我得到以下控制台日志:
true
true
true
true
true
true
...
线程永远不会终止。你能解释一下吗?
答案 0 :(得分:2)
假设您的while循环发生在GUI线程上,您永远不会放弃对窗口的控制(因为您处于循环中)。您还应该发现您的Invoke永远不会返回。 (它要求主线程通过在窗口的消息队列中放置一条消息来执行某些操作,但是主线程忙,所以它永远不会使消息出列)
如果这只是测试代码,您可以使用BeingInvoke,但实际上,您不应该在UI线程的后台线程上休眠并检查是否处于活动状态。
相反,让后台线程通过调用委托来通知你的窗口,或者(更好)使用BackgroundWorker(Winforms)或任务,并通过.ContinueWith()调用通知你的窗口已经完成了。