0

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

4

2 回答 2

1

这两种方法都是事件处理程序。它们可能来自某种监听代码,我希望它们是从非 UI 线程调用的(例如,通常是一个正在监听的线程池线程)。您可以通过设置断点并查看调试器中的线程窗口来检查。
因此,您将需要应用 winforms 从非 UI 线程更新 UI 的方式。
如果您搜索 SO,您应该会找到很多关于如何做到这一点的信息。例如
,从不同线程更新 UI
如何从 C# 中的另一个线程更新 GUI?

于 2012-04-07T13:04:51.933 回答
0

一些背景知识:不允许在 UI 线程以外的线程中运行的进程直接访问任何 UI 控件。您的 WPF ServerProc 运行在与 UI 不同的线程中,这需要Dispatcher帮助您从 ServerProc 线程与 UI 线程中的 UI 控件进行通信。

如果您的 ServerProc(在 WPF 或 WinForms 中)在 UI 线程中运行,则无需将其与Dispatcher.Invoke调用一起包围。

对您而言,您可以将 ServerProc 放入BackgroundWorker(MSDN 示例)中。您的DoWork方法将包含执行工作的代码的核心,然后根据 ServerProc 的工作方式,您可以使用ProgressChanged这两种示例 WPF 方法正在执行的操作。ProgressChanged有一个传入的参数,您将指示它是错误还是已收到数据,并且在函数内部您可以显示适当的信息。看看 MSDN 文档,因为他们有一个很好的例子。

需要指出的重要一点是,这ProgressChanged发生在 UI 线程上,因此您无需使用 Invoke 围绕对 UI 控件的调用;只是正常打电话给他们。当您的 ServerProc 完成其工作时,RunWorkerCompleted这可能是显示数据的另一个选项也是如此。

最后,如果您确实必须从您的线程中访问一个 UI 控件,您可以执行与您的 WPF 代码示例非常相似的操作。看看MethodInvoker。而不是 Dispatcher,您实际上只是从您的主窗体中调用它。

于 2012-04-07T13:05:38.720 回答