在WinForms应用程序中,我启动工作线程,将数据添加到根XElement
。
然后在主线程中我需要等待工作线程完成它的工作(以获得完整的XElement
),并将此XElement输出到textarea
。
如果我在主线程上调用.Join()
- 它会冻结,直到另一个线程停止(并且用户无法单击主窗体上的任何按钮)。
是否可以在等待另一个线程完成它的工作时取消阻塞主线程?
我试过了:
1
BeginInvoke(new Action(() => {
XmlManager.whReady.WaitOne();
xDocString = xResultDoc.ToString();
}));
2
string xDocString = String.Empty;
new Thread(() => { xDocString = XelementToString(); }).Start();
txtXmlTree.Text = xDocString;
public string XelementToString() {
XmlManager.whReady.WaitOne();
return xResultDoc.ToString();
}
但它没有效果。
EventWaitHandle XmlManager.whReady.WaitOne();
在工作线程关闭之前就是.Set()
。
答案 0 :(得分:1)
是的,您可以使用async / await
string docString = await Task.Run(() => {
XmlManager.whReady.WaitOne();
return xResultDoc.ToString();
}).ConfigureAwait(true);
//Execution flow will resume here once the thread is done.
....
//Now do something here with the text (e.g. display it).
...
例如,如果您想在点击按钮上运行此功能,则可以(请注意 async 修饰符):
private async void button1_Click(object sender, EventArgs e)
{
...The code above goes here...
}
至于为什么你的代码没有按预期工作(你的两次尝试):
xDocString
准备好使用。它不起作用。到执行此行时txtXmlTree.Text = xDocString;
,线程可能已经或可能没有完成执行(很可能没有完成)。 我希望你现在明白为什么await
是更好的选择。您不必将工作程序与主线程同步,您不必担心上下文切换并确保UI代码在UI线程上执行。
答案 1 :(得分:0)
您可以使用BackgroundWorker类,因为它是WinForm应用程序。
BackgroundWorker将让子任务在后台运行,并在完成后通知主表单(以及进度,如果需要),因此主表单将能够在文本中显示输出区域任务完成后区域。