国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

BackgroundWorker原理剖析

2019-11-17 03:08:29
字體:
來源:轉載
供稿:網友

BackgroundWorker原理剖析

BackgroundWorker類位于System.ComponentModel命名空間下,主要用來異步執行一個長時間的操作,然后,在完成事件中安全更新UI的控件屬性。UI中的控件是不允許非創建該控件的線程修改的。典型用法如下:

BackgroundWorker m_worker = new BackgroundWorker();// 設置支持進度報告、異步取消功能,默認都為falsem_worker.WorkerReportsPRogress = true;m_worker.WorkerSupportsCancellation = true;// 綁定事件m_worker.DoWork += m_worker_DoWork;m_worker.ProgressChanged += m_worker_ProgressChanged;m_worker.RunWorkerCompleted += m_worker_RunWorkerCompleted;void m_worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {    if (e.Cancelled == true) {         // 處理取消        return;    } else if (e.Error != null) {        // 處理異常        return;    }        // 在UI中顯示結果    // txtBox.Text = e.Result.ToString();}void m_worker_ProgressChanged(object sender, ProgressChangedEventArgs e) {    //progressBar.Value = e.ProgressPercentage;}void m_worker_DoWork(object sender, DoWorkEventArgs e) {    BackgroundWorker sendWorker = sender as BackgroundWorker;    for (int i = 0; i < 100; i++) {        // 做異步工作。。。。        // 報告進度        sendWorker.ReportProgress(i);        // 請求取消工作內容        if (sendWorker.CancellationPending == true) {            e.Cancel = true;            return;        }    }    // 可選,設置異步工作結果    e.Result = GetResultData();}

它的實現原理最重要的只有兩點:

一點是用異步委托間接使用線程池執行長時間的操作;

另外一點是通過AsyncOperationManager和AsyncOperation對調用RunWorkerAsync的線程SynchronizationContext進行抽象;

BackgroundWorker的源碼參見http://www.projky.com/dotnet/4.5.1/System/ComponentModel/BackgroundWorker.cs.html

首先從它的構造函數開始:

private delegate void WorkerThreadStartDelegate(object argument);private AsyncOperation                      asyncOperation = null;private readonly WorkerThreadStartDelegate  threadStart;private readonly SendOrPostCallback operationCompleted;private readonly SendOrPostCallback progressReporter;public BackgroundWorker(){    threadStart        = new WorkerThreadStartDelegate(WorkerThreadStart);    operationCompleted = new SendOrPostCallback(AsyncOperationCompleted);    progressReporter   = new SendOrPostCallback(ProgressReporter);}

定義了一個私有的委托類型WorkerThreadStartDelegate,以便于在該委托類型對象上直接調用BaginInvoke到線程池執行委托。SendOrPostCallback 是方便在UI線程(本質是調用RunWorkAsync時捕獲的當前線程同步上下文對象,為了容易理解,就叫它UI線程)上執行回調而創建的。而asyncOperation則通過Post方法在UI線程上異步來執行SendOrPostCallback委托。

在對DoWork添加事件后,需要調用RunWorkerAsync,有兩個重載,但我們只關注最后一個帶參數的:

public void RunWorkerAsync(object argument){    if (isRunning)    {        throw new InvalidOperationException(SR.GetString(SR.BackgroundWorker_WorkerAlreadyRunning));    }    isRunning = true;    cancellationPending = false;        asyncOperation = AsyncOperationManager.CreateOperation(null);    threadStart.BeginInvoke(argument,                            null,                            null);}

其實,asyncOperation = AsyncOperationManager.CreateOperation(null);這一行代碼,等同于下面的代碼:

if (SynchronizationContext.Current == null) {    SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());}SynchronizationContext currentContext = SynchronizationContext.Current;asyncOperation = AsyncOperation.CreateOperation(null, currentContext)

簡單來說,就是獲得當前的SynchronizationContext的對象,如果不存在,則創建一個默認的(基于線程池實現的)。并讓asyncOperation擁有SynchronizationContext的引用。

在.NET中,有很多種SynchronizationContext的子類,比如Winform里面的WindowsFormsSynchronizationContext類,WPF里面的DispatcherSynchronizationContext類,asp.net里面的AspNetSynchronizationContext類。重點是,當在Winform的UI線程中訪問SynchronizationContext.Current屬性,獲得的就是WindowsFormsSynchronizationContext的對象。

那么,最終,AsyncOperation的Post方法,就是直接調用SynchronizationContext的Post方法,來實現在UI中回調的目的。

public void Post(SendOrPostCallback d, object arg){    VerifyNotCompleted();    VerifyDelegateNotNull(d);    syncContext.Post(d, arg);}

還有一點,threadStart.BeginInvoke會用線程池中的線程執行類似如下的代碼:

object workerResult = null;Exception error = null;bool cancelled = false;try{    DoWorkEventArgs doWorkArgs = new DoWorkEventArgs(argument);    DoWorkEventHandler handler = (DoWorkEventHandler)(Events[doWorkKey]);    if (handler != null)    {        handler(this, doWorkArgs);    }    if (doWorkArgs.Cancel)    {        cancelled = true;    }    else    {        workerResult = doWorkArgs.Result;    }}catch (Exception exception){    error = exception;}RunWorkerCompletedEventArgs e =     new RunWorkerCompletedEventArgs(workerResult, error, cancelled); asyncOperation.PostOperationCompleted(operationCompleted, e);

其中,對DoWork事件的聲明如下:

private static readonly object doWorkKey = new object();public event DoWorkEventHandler DoWork{    add{        this.Events.AddHandler(doWorkKey, value);    }    remove{        this.Events.RemoveHandler(doWorkKey, value);    }}

Events是從Component下派生來的protected EventHandlerList對象。

從BackgroundWorker的實現可以看出,它的實現是普遍性的,并不一定要用在Winform或者WPF中。

本文引用的源碼參考列表可以從扣丁格魯上查看。

http://www.projky.com/dotnet/4.5.1/System/ComponentModel/BackgroundWorker.cs.html

http://www.projky.com/dotnet/4.5.1/System/ComponentModel/AsyncOperation.cs.html

http://www.projky.com/dotnet/4.5.1/System/ComponentModel/AsyncOperationManager.cs.html

http://www.projky.com/dotnet/4.5.1/System/Threading/SynchronizationContext.cs.html

http://www.projky.com/dotnet/4.5.1/System/Windows/Forms/WindowsFormsSynchronizationContext.cs.html

http://www.projky.com/dotnet/4.5.1/System/Windows/Threading/DispatcherSynchronizationContext.cs.html

http://www.projky.com/dotnet/4.5.1/System/Web/AspNetSynchronizationContext.cs.html

關于基于事件的異步編程設計模式EAP更多參考請見http://msdn.microsoft.com/zh-cn/library/hkasytyf(v=vs.110).aspx


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 斗六市| 黄山市| 兴业县| 疏勒县| 乳山市| 高雄县| 财经| 塔城市| 甘孜| 崇州市| 察雅县| 山阳县| 鄂托克前旗| 贵南县| 泸溪县| 双鸭山市| 开封市| 什邡市| 林芝县| 通榆县| 宝清县| 安仁县| 孝感市| 同心县| 南郑县| 桂阳县| 香港| 镇康县| 正宁县| 泊头市| 揭阳市| 沁阳市| 平江县| 贞丰县| 弥渡县| 新民市| 晴隆县| 阿拉善右旗| 新龙县| 法库县| 防城港市|