[英]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
進行此工作,然后只有添加檢索到的項目的Combobox
的RunWorkerCompleted
事件。
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.