【问题标题】: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 工作正常!

标签: c# multithreading events terminate


【解决方案1】:

假设您的 while 循环发生在 GUI 线程上,您永远不会放弃对窗口的控制(因为您处于循环中)。您还应该发现您的 Invoke 永远不会返回。 (它通过在窗口的消息队列中放置一条消息来要求主线程做某事,但是你的主线程很忙,所以它永远不会使消息出队)

如果这只是测试代码,您可以改用 BeingInvoke,但实际上,您不应该在 UI 线程的后台线程上处于休眠状态并检查活动状态。

相反,让后台线程在完成时通过调用委托通知您的窗口,或者(更好)使用 BackgroundWorker (Winforms) 或 Task,使用 .ContinueWith() 调用来通知您的窗口已完成。

【讨论】:

    猜你喜欢
    • 2019-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多