将WPF调度程序转换为Winforms BGworker?

时间:2012-04-07 12:39:00

标签: wpf winforms multithreading backgroundworker dispatcher

我最近获得了服务器控制台包装器的一些源代码。该程序最初是在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中没有这样的东西 - 是否有办法将其更改为后台工作者或其他东西(我几乎没有做任何多线程)?

如果有人可以提供帮助,那就太好了!

感谢。

2 个答案:

答案 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,你只是从你的主表单中调用它。