可能我没有正确理解这个主题。这里有个问题...
C# Windows 应用程序 (.NET 2.0)。MainForm 有一个“查询”按钮。当用户推送它时,应该会发生以下情况:
private void btnQuery_Click(object sender, EventArgs e)
{
querier = new Querier();
OutputForm outputForm = new OutputForm();
querier.ProcessAll(outputForm.OutputReceived);
outputForm.ShowDialog();
}
Querier
是工人。它创建一个后台线程并运行它来做一些事情。这OutputForm
是一个带有txtOutput
多行文本框的简单表单,应该显示工作线程的输出。
为了允许工作线程发送其输出,querier.ProcessAll()
方法接收一个回调处理程序。这是它的实现:
public void OutputReceived(string message)
{
if (this.InvokeRequired)
this.Invoke((MethodInvoker)delegate() { this.OutputReceived(message); });
else if (!string.IsNullOrEmpty(message))
txtOutput.AppendText(message + Environment.NewLine);
}
所以基本上工作线程运行并使用使用 的OutputReceived()
方法发送输出Invoke()
,因为工作线程不能直接访问 txtOutput 字段。
请注意,这outputForm.ShowDialog()
称为 AFTER querier.ProcessAll()
。那是因为ShowDialog()
正在阻塞。
但问题就在这里。如果工作线程在实际显示对话框之前发送任何输出,我会收到有关跨线程操作的异常!this.InvokeRequired()
当我调试它时,我在方法中看到由于某种原因OutputReceived()
返回"false"
!这就是为什么工作线程尝试txtOutput
直接访问并崩溃的原因。
问题显然是关于线程和ShowDialog()
. 如果我Thread.Sleep()
在工作线程的开头添加,则会显示对话框,然后一切正常。
你能解释一下这种行为吗?