简体   繁体   English

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

[英]Howto wait work thread in the main Form?

after reading a few articles, I am still not sure I understand Multi-threading to solve my particular problem. 在阅读了几篇文章之后,我仍然不确定我是否了解多线程解决了我的特定问题。

I have a Main form which will start a background worker thread(worker). 我有一个主窗体,它将启动一个后台工作线程(worker)。 The worker thread will doing a While(!Stopping) infinity loop and will sleep at end of each iteration terminate by global Stopping object(Read only lock object). 工作线程将执行While(!Stopping)无限循环,并在每次迭代结束时进入休眠状态,并由全局Stopping对象(只读锁定对象)终止。 With working fine when user press Stop button, the worker will stop after current iteration. 当用户按下“停止”按钮时,由于工作正常,工作人员将在当前迭代后停止。

Now I want when user close the main form, it will set Stop flag first, let the worker thread finish its current job. 现在我想当用户关闭主窗体时,它将首先设置Stop标志,让工作线程完成当前的工作。 After that the main form will close. 之后,主窗体将关闭。 Seems simple enough, but I couldn't make it working. 看起来很简单,但我无法使其正常工作。

I tried either worker.Join(), or test woker.IsAlive in a while loop, but both case will lock the application(Main form) after a few seconds for some reason ? 我在一个while循环中尝试了worker.Join()或test woker.IsAlive,但是由于某种原因,两种情况都将在几秒钟后锁定应用程序(主要形式)?

The following is my code inside Form_Closing event handler (not working): 以下是我在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");

One thing interesting is that the worker thread seems always writes log event until the end of each loop iteration, then the rest of the log entry will be main form event inside the while(worker.IsAlive) loop. 有趣的是,工作线程似乎总是在每次循环迭代结束之前写入日志事件,然后其余的日志条目将成为while(worker.IsAlive)循环内的主要表单事件。

Join will always wait on the thread, using it in the UI thread will make application seem to be locked. Join将始终在线程上等待,在UI线程中使用它会使应用程序似乎被锁定。 IsAlive do not block anything in the GUI thread, it's your Thread.Sleep. IsAlive不会阻止GUI线程中的任何内容,这是您的Thread.Sleep。

do somethnig like this instead: 做这样的事情:

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

You are creating a deadlock somehow put a break point everywhere you request and release the locking object. 您正在以某种方式创建死锁,在您请求并释放锁定对象的任何地方都放置了一个断点。 Also you can use the system.threading.monitor class to test to see if the lock is available rather then creating a deadlock. 您也可以使用system.threading.monitor类测试该锁是否可用,然后创建死锁。 Get Very familiar with the threads window in VS. 非常熟悉VS中的线程窗口。

Keep in mind that any code you use that causes the UI thread to suspend its normal obligation of pumping messages will manifest itself as a hang to the user. 请记住,您使用的任何导致UI线程挂起其正常消息发送义务的代码都将表现为对用户的挂起。 In other words, do not call any method which may block including Thread.Join , Thread.Sleep , WaitHandle.WaitOne , etc. 换句话说,请勿调用任何可能阻塞的方法,包括Thread.JoinThread.SleepWaitHandle.WaitOne等。

Since you want the worker to terminate upon closing the form then I suggest letting the form close after the stop signal has been sent to the worker thread. 因为您希望工作程序在关闭表单时终止,所以我建议在将停止信号发送到工作程序线程之后让表单关闭。 Add a Thread.Join call to the entry point of your application after the call to Application.Run . 在对Application.Run的调用之后,将Thread.Join调用添加到应用程序的入口点。 Since you are shutting down the application it is safe to call Thread.Abort if the thread does not respond in a timely manner. 由于您正在关闭应用程序,因此,如果线程没有及时响应,则可以安全地调用Thread.Abort Here is some example code. 这是一些示例代码。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM