The Labs \ Source Viewer \ SSCLI \ System.ComponentModel \ BackgroundWorker

  1. //------------------------------------------------------------------------------
  2. // <copyright file="BackgroundWorker.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.ComponentModel
  16. {
  17.     using System.ComponentModel.Design.Serialization;
  18.     using System.Diagnostics;
  19.     using System.Security.Permissions;
  20.     using System.Threading;
  21.    
  22.     [SRDescription(SR.BackgroundWorker_Desc), DefaultEvent("DoWork"), HostProtection(SharedState = true)]
  23.     public class BackgroundWorker : Component
  24.     {
  25.         // Private statics
  26.         private static readonly object doWorkKey = new object();
  27.         private static readonly object runWorkerCompletedKey = new object();
  28.         private static readonly object progressChangedKey = new object();
  29.        
  30.         // Private instance members
  31.         private bool canCancelWorker = false;
  32.         private bool workerReportsProgress = false;
  33.         private bool cancellationPending = false;
  34.         private bool isRunning = false;
  35.         private AsyncOperation asyncOperation = null;
  36.         private readonly WorkerThreadStartDelegate threadStart;
  37.         private readonly SendOrPostCallback operationCompleted;
  38.         private readonly SendOrPostCallback progressReporter;
  39.        
  40.         public BackgroundWorker()
  41.         {
  42.             threadStart = new WorkerThreadStartDelegate(WorkerThreadStart);
  43.             operationCompleted = new SendOrPostCallback(AsyncOperationCompleted);
  44.             progressReporter = new SendOrPostCallback(ProgressReporter);
  45.         }
  46.        
  47.         private void AsyncOperationCompleted(object arg)
  48.         {
  49.             isRunning = false;
  50.             cancellationPending = false;
  51.             OnRunWorkerCompleted((RunWorkerCompletedEventArgs)arg);
  52.         }
  53.        
  54.         [Browsable(false), SRDescription(SR.BackgroundWorker_CancellationPending)]
  55.         public bool CancellationPending {
  56.             get { return cancellationPending; }
  57.         }
  58.        
  59.         public void CancelAsync()
  60.         {
  61.             if (!WorkerSupportsCancellation) {
  62.                 throw new InvalidOperationException(SR.GetString(SR.BackgroundWorker_WorkerDoesntSupportCancellation));
  63.             }
  64.            
  65.             cancellationPending = true;
  66.         }
  67.        
  68.         [SRCategory(SR.PropertyCategoryAsynchronous), SRDescription(SR.BackgroundWorker_DoWork)]
  69.         public event DoWorkEventHandler DoWork {
  70.             add { this.Events.AddHandler(doWorkKey, value); }
  71.             remove { this.Events.RemoveHandler(doWorkKey, value); }
  72.         }
  73.        
  74.         /// <include file='doc\BackgroundWorker.uex' path='docs/doc[@for="BackgroundWorker.IsBusy"]/*' />
  75.         [Browsable(false), SRDescription(SR.BackgroundWorker_IsBusy)]
  76.         public bool IsBusy {
  77.             get { return isRunning; }
  78.         }
  79.        
  80.         /// <include file='doc\BackgroundWorker.uex' path='docs/doc[@for="BackgroundWorker.OnDoWork"]/*' />
  81.         protected virtual void OnDoWork(DoWorkEventArgs e)
  82.         {
  83.             DoWorkEventHandler handler = (DoWorkEventHandler)(Events[doWorkKey]);
  84.             if (handler != null) {
  85.                 handler(this, e);
  86.             }
  87.         }
  88.        
  89.         /// <include file='doc\BackgroundWorker.uex' path='docs/doc[@for="BackgroundWorker.OnRunWorkerCompleted"]/*' />
  90.         protected virtual void OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
  91.         {
  92.             RunWorkerCompletedEventHandler handler = (RunWorkerCompletedEventHandler)(Events[runWorkerCompletedKey]);
  93.             if (handler != null) {
  94.                 handler(this, e);
  95.             }
  96.         }
  97.        
  98.         protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
  99.         {
  100.             ProgressChangedEventHandler handler = (ProgressChangedEventHandler)(Events[progressChangedKey]);
  101.             if (handler != null) {
  102.                 handler(this, e);
  103.             }
  104.         }
  105.        
  106.         [SRCategory(SR.PropertyCategoryAsynchronous), SRDescription(SR.BackgroundWorker_ProgressChanged)]
  107.         public event ProgressChangedEventHandler ProgressChanged {
  108.             add { this.Events.AddHandler(progressChangedKey, value); }
  109.             remove { this.Events.RemoveHandler(progressChangedKey, value); }
  110.         }
  111.        
  112.         // Gets invoked through the AsyncOperation on the proper thread.
  113.         private void ProgressReporter(object arg)
  114.         {
  115.             OnProgressChanged((ProgressChangedEventArgs)arg);
  116.         }
  117.        
  118.         // Cause progress update to be posted through current AsyncOperation.
  119.         public void ReportProgress(int percentProgress)
  120.         {
  121.             ReportProgress(percentProgress, null);
  122.         }
  123.        
  124.         // Cause progress update to be posted through current AsyncOperation.
  125.         public void ReportProgress(int percentProgress, object userState)
  126.         {
  127.             if (!WorkerReportsProgress) {
  128.                 throw new InvalidOperationException(SR.GetString(SR.BackgroundWorker_WorkerDoesntReportProgress));
  129.             }
  130.            
  131.             ProgressChangedEventArgs args = new ProgressChangedEventArgs(percentProgress, userState);
  132.            
  133.             if (asyncOperation != null) {
  134.                 asyncOperation.Post(progressReporter, args);
  135.             }
  136.             else {
  137.                 progressReporter(args);
  138.             }
  139.         }
  140.        
  141.         public void RunWorkerAsync()
  142.         {
  143.             RunWorkerAsync(null);
  144.         }
  145.        
  146.         public void RunWorkerAsync(object argument)
  147.         {
  148.             if (isRunning) {
  149.                 throw new InvalidOperationException(SR.GetString(SR.BackgroundWorker_WorkerAlreadyRunning));
  150.             }
  151.            
  152.             isRunning = true;
  153.             cancellationPending = false;
  154.            
  155.             asyncOperation = AsyncOperationManager.CreateOperation(null);
  156.             threadStart.BeginInvoke(argument, null, null);
  157.         }
  158.        
  159.         [SRCategory(SR.PropertyCategoryAsynchronous), SRDescription(SR.BackgroundWorker_RunWorkerCompleted)]
  160.         public event RunWorkerCompletedEventHandler RunWorkerCompleted {
  161.             add { this.Events.AddHandler(runWorkerCompletedKey, value); }
  162.             remove { this.Events.RemoveHandler(runWorkerCompletedKey, value); }
  163.         }
  164.        
  165.         [SRCategory(SR.PropertyCategoryAsynchronous), SRDescription(SR.BackgroundWorker_WorkerReportsProgress), DefaultValue(false)]
  166.         public bool WorkerReportsProgress {
  167.             get { return workerReportsProgress; }
  168.             set { workerReportsProgress = value; }
  169.         }
  170.        
  171.         [SRCategory(SR.PropertyCategoryAsynchronous), SRDescription(SR.BackgroundWorker_WorkerSupportsCancellation), DefaultValue(false)]
  172.         public bool WorkerSupportsCancellation {
  173.             get { return canCancelWorker; }
  174.             set { canCancelWorker = value; }
  175.         }
  176.        
  177.         private delegate void WorkerThreadStartDelegate(object argument);
  178.        
  179.         private void WorkerThreadStart(object argument)
  180.         {
  181.             object workerResult = null;
  182.             Exception error = null;
  183.             bool cancelled = false;
  184.            
  185.             try {
  186.                 DoWorkEventArgs doWorkArgs = new DoWorkEventArgs(argument);
  187.                 OnDoWork(doWorkArgs);
  188.                 if (doWorkArgs.Cancel) {
  189.                     cancelled = true;
  190.                 }
  191.                 else {
  192.                     workerResult = doWorkArgs.Result;
  193.                 }
  194.             }
  195.             catch (Exception exception) {
  196.                 error = exception;
  197.             }
  198.            
  199.             RunWorkerCompletedEventArgs e = new RunWorkerCompletedEventArgs(workerResult, error, cancelled);
  200.            
  201.             asyncOperation.PostOperationCompleted(operationCompleted, e);
  202.         }
  203.        
  204.     }
  205. }

Developer Fusion