繁体   English   中英

BackgroundWorker进程需要引发要在主(UI)线程上处理的自定义事件

[英]BackgroundWorker process needs to raise custom events to be handled on the main (UI) thread

我有一个用于大型CSV文件的解析器类。 解析方法的逐行读取大文件的工作是在backgroundWorker中完成的。 使用backgroundWorker.ReportProgress方法将完成百分比信息传递给UI线程,以便表单上的进度条可以完成其工作。 很好

但是,我还想提出一个自定义事件,该事件将从CSV文件的第一行获取的字段名称列表发送回UI(WPF),以便可以将它们放置在下拉列表中。 我还想通过事件通知用户解析器是否遇到格式错误的行或其他障碍。

我在后台执行的解析器进程可以引发一个事件吗? 还是必须将SynchronizationContext.Current从主UI线程传递到我的解析器类,然后再使用Post方法?

如果您绝对必须DoWork处理程序中安排UI线程上的工作,最简单的方法是使用Dispatcher.Invoke

public partial class MainWindow : Window
{
    public MainWindow()
    {
        this.InitializeComponent();

        var worker = new BackgroundWorker();

        worker.DoWork += (s, e) =>
        {
            // Suppose we've done some processing and need to notify the UI.
            // We're on the background thread, so we can't manipulate the UI directly.
            this.Dispatcher.Invoke(new Action(() =>
            {
                // This will actually run on the UI thread.
                this.Label.Content = "hello from the background thread.";
            }));
        };

        worker.RunWorkerAsync();
    }
}

关于事件及其执行线程同步的神奇能力,似乎存在很多困惑,因此请允许我大声疾呼。

事件是美化的多播委托。 引发事件时,将在引发事件的线程上调用其调用列表中的每个委托。 因此,如果仅在自定义解析器类中创建事件以使其从DoWork处理程序中引发,则该事件的处理程序仍将在后台线程上执行,并且仍将需要找到一种方法来切换到UI同步上下文-通过在新事件的处理程序内执行一些Invoke / SynchronizationContext.Post / Send魔术,或者通过调用/发布/发送实际事件引发逻辑。

在UI线程上运行开箱即用事件(例如RunWorkerCompletedProgressChanged处理程序的原因是,为方便起见, BackgroundWorker 实际上在UI线程上引发了这些事件。 是的,您可以通过捕获SynchronizationContext ,然后在自定义解析器类中向其发布/发送事件引发逻辑来产生类似的行为。 另外,如果选择在后台线程上引发事件,则始终可以在WPF组件的处理程序内部使用Dispatcher.Invoke

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM