我最近获得了服务器控制台包装器的一些源代码。该程序最初是在WPF中,部分代码是:
private void ServerProc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
ConsoleTextBlock.Text += e.Data + "\r\n";
ConsoleScroll.ScrollToEnd();
}));
}
private void ServerProc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
ConsoleTextBlock.Text += e.Data + "\r\n";
ConsoleScroll.ScrollToEnd();
ParseServerInput(e.Data);
}));
}
它在两个空洞中都有这个注释:
//您必须通过Dispatcher执行此操作,因为此方法是 由不同的线程调用
但是在WinForms中没有这样的东西 - 是否有办法将其更改为后台工作者或其他东西(我几乎没有做任何多线程)?
如果有人可以提供帮助,那就太好了!
感谢。
答案 0 :(得分:1)
这两种方法都是事件处理程序。有可能它们来自某种监听代码,我希望它们是从非UI线程调用的(例如,通常是正在进行监听的线程池线程)。您可以通过设置断点并查看调试器中的线程窗口来检查它
因此,您需要应用从非UI线程更新UI的winforms方式
如果你搜索SO,你应该找到很多关于如何做到这一点。 E.g
Updating UI from a different thread
How to update GUI from another thread in C#?
答案 1 :(得分:0)
某些背景信息:不允许在UI线程以外的线程中运行的进程直接访问任何UI控件。您的WPF ServerProc运行在与UI不同的线程中,这需要Dispatcher
帮助您从ServerProc线程回传到UI线程中的UI控件。
如果你的ServerProc - 在WPF或WinForms中 - 在UI线程中运行,你不需要用Dispatcher.Invoke
调用来包围它。
对于您,您可以将您的ServerProc放在BackgroundWorker (MSDN example)中。您的DoWork
方法将包含执行工作的代码,然后根据ServerProc的工作方式,您可以使用ProgressChanged
来执行示例WPF方法正在执行的操作。 ProgressChanged
传递了一个参数,您可以指示它是错误还是已收到数据,并且在函数内部可以显示相应的信息。看一下MSDN文档,因为它们有一个很好的例子。
重要的是要指出,ProgressChanged
发生在UI线程上,因此您不需要使用Invoke包围对UI控件的调用;只是正常打电话给他们同样适用于RunWorkerCompleted
,这可能是您的ServerProc完成其工作时显示数据的另一个选项。
最后,如果您实际上必须从线程中访问UI控件,那么您可以执行与WPF代码示例非常相似的操作。看看MethodInvoker。而不是Dispatcher,你只是从你的主表单中调用它。