WinForms多线程问题 [英] WinForms multithreading issue
问题描述
我有一个线程在后台执行一些工作,并使用Invoke,BeginInvoke方法将更新传递给Form.线程是在显示表单后创建的,因此在那里没有问题.
Ive got a thread that does some work in the background and passes updates to the Form using the Invoke, BeginInvoke methods. The thread is created after the form is displayed so no issue there.
问题是如何正确关闭.我的工作线程有能力被要求退出,并且将在此之后不久(毫秒)退出.
The issue is how to correctly shutdown. My worker thread has the ability to be asked to exit, and will exit some time soon after that (miliseconds).
但是,如果首先关闭了窗体,则调用"内容将中断.我尝试将Thread.Join添加到窗体关闭事件中,但是这当然会导致死锁,甚至对于BeginInvoke也是如此,因为Thread.Join会阻塞该线程上的BeginInvoke ...
However if the form has closed first the Invoke stuff breaks. I tried adding a Thread.Join to the forms closing event, but of course this causes a deadlock, even for BeginInvoke since somhow a Thread.Join blocks a BeginInvoke on that thread...
关闭表单并干净地关闭其工作线程的正确方法是什么?
What is the correct way to close the form and shutdown its worker thread cleanly?
基本当前代码:
volatile bool abort;
void WorkerThread()
{
while(!abort)DoStuffIncludingInvokesOnThisForm();
}
void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
abort = true;
workerThread.Join();//will deadlock with DoStuffIncludingInvokesOnThisForm
//if get here before workerThread has exited, invokes will fail if workerthread is still in DoStuffIncludingInvokesOnThisForm
}
推荐答案
在Form.Closing
事件处理程序中,将Cancel
属性设置为true,以暂时推迟关闭表单,直到工作线程完成.工作线程终止后,您可以在表单上重新发出Close
命令.
From the Form.Closing
event handler set the Cancel
property to true to temporarily defer closing of the form until the worker thread has finished. Once the worker thread has terminated then you can reissue the Close
command on the form.
public class MyForm : Form
{
private volatile bool abort = false;
private bool IsCloseRequested = false;
private bool IsWorkerThreadComplete = false;
private void MyForm_Closing(object sender, FormClosingEventArgs args)
{
if (!IsWorkerThreadComplete)
{
args.Cancel = true;
IsCloseRequested = true;
abort = true;
}
}
void WorkerThread()
{
try
{
while (!abort) DoStuffIncludingInvokesOnThisForm();
}
finally
{
OnWorkerThreadComplete();
}
}
private void OnWorkerThreadComplete()
{
if (InvokeRequired)
{
Invoke(((MethodInvoker)() => OnWorkerThreadComplete), null);
}
else
{
IsWorkerThreadComplete = true;
if (IsCloseRequested) Close();
}
}
}
这篇关于WinForms多线程问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!