【问题标题】:Convert a WPF dispatcher to Winforms BGworker?将 WPF 调度程序转换为 Winforms BGworker?
【发布时间】:2012-04-07 12:39:00
【问题描述】:

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

【问题讨论】:

    标签: wpf winforms multithreading backgroundworker dispatcher


    【解决方案1】:

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

    【讨论】:

    • 谢谢,但我不太确定如何将它应用到我的代码中 - 我使用 VB.NET 好多了,仍然习惯 C#
    【解决方案2】:

    一些背景知识:在 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,您实际上只是从您的主窗体中调用它。

    【讨论】:

    • 问题是两个 ServerProc 方法都是事件处理程序 - 并且将由非 UI 线程上的现有代码调用。我注意到 BackgroundWorker 在这种情况下如何提供帮助?我认为他不想重写现有的服务器侦听/事件触发代码 - 只是事件处理程序 - 已经在非 UI 线程上。
    • 非常感谢! ;D 我使用了方法调用程序!不,我终于可以让这个应用程序运行起来了。很大的帮助。谢谢。
    • @AlexOgden 如果这为您提供了解决方案,那么您应该通过单击左侧的勾号将其标记为已接受的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多