簡體   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