Analysis of BackgroundWorker principles

Source: Internet
Author: User

The BackgroundWorker class is located in the namespace of System. ComponentModel. It is mainly used to asynchronously perform a long operation and then securely update the control attributes of the UI in the event completion. Controls in the UI are not allowed to be modified by threads that do not create the controls. The typical usage is as follows:

BackgroundWorker m_worker = new BackgroundWorker (); // you can specify progress report and asynchronous cancellation. The default value is progress = true; m_worker.workersuppscanscancellation = true; // bind event 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. Cancelled = true) {// handle canceled return;} else if (e. Error! = Null) {// handle the exception return;} // display the result in the 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 ++) {// do asynchronous work .... // Report the progress of sendWorker. reportProgress (I); // request to cancel the work content if (sendWorker. cancellationPending = true) {e. cancel = true; return ;}// (optional) sets asynchronous work result e. result = GetResultData ();}

The most important principle is the following:

One point is to use Asynchronous delegation to indirectly use the thread pool for long-time operations;

Another point is to abstract the thread SynchronizationContext that calls RunWorkerAsync through AsyncOperationManager and AsyncOperation;

For the source code of BackgroundWorker, see http://www.projky.com/dotnet/4.5.1/System/ComponentModel/BackgroundWorker.cs.html

Start with its constructor:

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);}

Defines a private delegate type WorkerThreadStartDelegate, so that you can directly call BaginInvoke on the delegate type object to execute the delegate in the thread pool. SendOrPostCallback is created to facilitate callback execution on the UI thread (essentially the context object captured when RunWorkAsync is called. AsyncOperation executes the SendOrPostCallback delegate asynchronously on the UI thread through the Post method.

After adding an event to DoWork, you need to call RunWorkerAsync. There are two reloads, but we only pay attention to the last one with parameters:

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);}

In fact, asyncOperation = AsyncOperationManager. CreateOperation (null); this line of code is equivalent to the following code:

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

To put it simply, it is to obtain the current SynchronizationContext object. If it does not exist, a default (implemented based on the thread pool) is created ). And enable asyncOperation to have reference to SynchronizationContext.

There are many SynchronizationContext subclasses in. NET, such as the WindowsFormsSynchronizationContext class in Winform, The DispatcherSynchronizationContext class in WPF, And the AspNetSynchronizationContext class in ASP. NET.The point is that when you access the SynchronizationContext. Current attribute in the Winform UI thread, the obtained object is the WindowsFormsSynchronizationContext object.

In the end, the Post method of AsyncOperation is to directly call the Post method of SynchronizationContext to implement the purpose of callback in the UI.

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

Another point is that threadStart. BeginInvoke uses threads in the thread pool to execute code similar to the following:

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);

The Declaration of the DoWork event is as follows:

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

Events is a protected EventHandlerList object generated under Component.

It can be seen from the implementation of BackgroundWorker that its implementation is universal and not necessarily used in Winform or WPF.

The source code reference list referenced in this article can be viewed from dinggru.

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

 

For more information about event-based asynchronous programming design patterns EAP, see http://msdn.microsoft.com/zh-cn/library/hkasytyf (v = vs.110). aspx

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.