如何在主窗体中等待工作线程?

时间:2010-10-06 05:10:59

标签: c# multithreading

在阅读了几篇文章之后,我仍然不确定我是否理解多线程来解决我的问题 特别的问题。

我有一个Main表单,它将启动后台工作线程(worker)。工作线程将执行While(!Stopping)无限循环,并在每次迭代结束时休眠,由全局Stopping对象(只读锁定对象)终止。当用户按下停止按钮时,工作正常 工人将在当前迭代后停止。

现在我希望当用户关闭主窗体时,它会先设置Stop标志,让工作线程 完成目前的工作。之后主表格将关闭。看起来很简单,但我无法使其正常工作。

我尝试了worker.Join(),或者在一个while循环中测试woker.IsAlive,但两种情况都会在几秒钟之后由于某种原因锁定应用程序(主窗体)?

以下是我在Form_Closing事件处理程序(不工作)中的代码:

               // Tell the thread to stop the file
                Stop();
                Logger.Info("Stopping the thread by Close the application");
               //Not working as well                    
               //worker.Join();
                while (worker.IsAlive)
                {
                    Thread.Sleep(5000);
                    Logger.Info("After sleep for 5 seconds");
                }
                Logger.Info("worker thread stopped");

有趣的是,工作线程似乎总是写入日志事件,直到每次循环迭代结束,然后其余的日志条目将成为主要的表单事件 while(worker.IsAlive)循环。

3 个答案:

答案 0 :(得分:2)

Join将始终在线程上等待,在UI线程中使用它将使应用程序似乎被锁定。 IsAlive不会阻止GUI线程中的任何内容,它是你的Thread.Sleep。

这样做一些事情:

while (worker.IsAlive)
{
    Thread.sleep(50);
    Application.DoEvents();
}

答案 1 :(得分:0)

你正在创建一个死锁,以某种方式在你请求的任何地方放置一个断点并释放锁定对象。您还可以使用system.threading.monitor类来测试锁定是否可用,而不是创建死锁。非常熟悉VS中的线程窗口。

答案 2 :(得分:0)

请记住,您使用的任何代码都会导致UI线程暂停其正常的泵送消息义务,这些代码将表现为对用户的挂起。换句话说,请勿调用任何可能阻止包含Thread.JoinThread.SleepWaitHandle.WaitOne等的方法。

由于您希望工作人员在关闭表单时终止,因此我建议在停止信号发送到工作线程后让表单关闭。在致电Thread.Join后,向您的应用程序的入口点添加Application.Run电话。由于您正在关闭应用程序,因此如果线程没有及时响应,则可以安全地调用Thread.Abort。这是一些示例代码。

public void Main(string[] args)
{
  var form = new YourForm();
  Application.Run(form);
  if (!form.WorkerThread.Join(TIME_TO_WAIT))
  {
    form.WorkerThread.Abort();
  }
}