簡體   English   中英

這是使用后台工作者的正確方法嗎?

[英]Is it a correct way of using background worker?

在某些代碼中看到了這一點,但對我來說卻毫無意義,所以我想知道這是否是使用backgreound工作者的正確方法?

它在Form_Load事件中像這樣使用:

    BackgroundWorker asyncWorker = new BackgroundWorker();
    asyncWorker.DoWork += new DoWorkEventHandler(AsynchDoWork);
    asyncWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(AsynchCompleted);
    asyncWorker.RunWorkerAsync();

   // a for each loop that can take some time to populate a combobx on the form

此外,在實現相同目標方面還有更好的選擇嗎? 除了背景工作者?

如果我理解正確,那么您實際上要問的是應該從后台線程還是從UI線程填充組合Combobox的值。

如果填充組合Combobox需要花費很長時間的原因是實際檢索這些條目需要花費很長時間-例如,如果要從數據庫中檢索它們,則可能應該在BackgroundWorker進行此工作,然后只有添加檢索到的項目的ComboboxRunWorkerCompleted事件。

RunWorkerCompleted事件雖然仍從后台線程運行,但它會在內部自動調用Invoke來訪問UI元素,因此更新UI元素沒有問題。

當然,長時間運行的垂耳有內部運行DoWork事件,而不是在同一個代碼塊中調用RunWorkerAsync ,在您的代碼示例。

相反,如果我們只是在談論大量現成的項目,並且由於數量原因,對AddRange的調用僅花費大量時間,則不能從后台線程調用此項目,因為只能訪問winforms控件從UI線程。

我將為此使用Task Parralell庫。 一個很好的教程是Task Parallel Library:1 of n 要根據某些后台任務的結果更新組合框,您可以執行以下操作

// Get UI scheduler. Use this to update ui thread in continuation.
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

// You can use TPL like this...
List<object> objList = new List<object>();
Task<object[]> task = Task.Factory.StartNew<object[]>(() =>
    {
        // Pull all your data into some object.
        object[] objArr = new object[] { "Some", "Stuff", "..." };
        return objArr;
    }, TaskCreationOptions.PreferFairness);

// Continuation firs after the antecedent task is completed.
task.ContinueWith(ant =>
    {
        // Get returned data set.
        object[] resultSet = (task.Result as object[]);

        // Check task status.
        switch (task.Status)
        {
            // Handle any exceptions to prevent UnobservedTaskException.             
            case TaskStatus.RanToCompletion:
                if (task.Result != null)
                {
                    // Update UI comboBox.
                }
                break;
            default:
                break;
        }
    }, CancellationToken.None, TaskContinuationOptions.None, uiScheduler);

在這里uiScheduler允許您從延續委托中更新ui線程,該延續線程會在先驗任務完成(成功或失敗)時觸發。

在這種情況下,延續也充當異常處理程序,以捕獲可能從后台線程引發的任何AggregateExceptions

我希望這有幫助。

我不確定范圍,我會創建BackgroundWorker作為類的成員。

BackgroundWorker使UI線程的工作變得輕松,並具有可輕松訪問更新進度的方法。

至於替代方案,這取決於您的目標是什么。 如果這是不更新UI的小任務,則可以選擇System.Threading.ThreadPool。

要回答“除了背景工作者以外,在實現相同目標上還有更好的選擇嗎?”的問題。

否。這是處理winforms長時間運行的阻止任務的最簡單方法。 還有其他方法(BeginInvoke),但是僅使用后台工作程序要容易得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM