事件后线程未完成
Posted
技术标签:
【中文标题】事件后线程未完成【英文标题】:Thread not finishing after Event 【发布时间】:2013-12-10 19:26:03 【问题描述】:看看这个简单的类:
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
...
线程永远不会终止。你能解释一下吗?
【问题讨论】:
你能检查一下当你改用BeginInvoke
时问题是否仍然存在吗?
显而易见的建议是它永远递归地调用自己。
我不确定,只是一个假设 - 您正在尝试调用处于无限 while 循环中的 GUI 线程上的方法。所以你的 this.tb_log.Invoke 调用永远不会结束
@Jeremy:不,该方法正在正确完成。当我添加 Console.Write("abc");在 log("Test") 之后,我在控制台中得到了 "abc"。
@ChrisK:谢谢,BeginInvoke 工作正常!
【参考方案1】:
假设您的 while 循环发生在 GUI 线程上,您永远不会放弃对窗口的控制(因为您处于循环中)。您还应该发现您的 Invoke 永远不会返回。 (它通过在窗口的消息队列中放置一条消息来要求主线程做某事,但是你的主线程很忙,所以它永远不会使消息出队)
如果这只是测试代码,您可以改用 BeingInvoke,但实际上,您不应该在 UI 线程的后台线程上处于休眠状态并检查活动状态。
相反,让后台线程在完成时通过调用委托通知您的窗口,或者(更好)使用 BackgroundWorker (Winforms) 或 Task,使用 .ContinueWith() 调用来通知您的窗口已完成。
【讨论】:
以上是关于事件后线程未完成的主要内容,如果未能解决你的问题,请参考以下文章
jquery是怎么实现:页面加载完毕,而图片未加载完成时,触发的事件?