2010-06-21 Marek Habersack <mhabersack@novell.com>
[mcs.git] / class / System / System.ComponentModel / BackgroundWorker.cs
blob9a7e0732186e1158772a6447d5eec5b65e5355b5
1 //
2 // BackgroundWorker.cs
3 //
4 // Authors:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2006 Novell, Inc.
8 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #if NET_2_0
31 using System.Collections.Generic;
32 using System.Threading;
34 namespace System.ComponentModel
36 #if !NET_2_1
37 [DefaultEvent ("DoWork")]
38 public class BackgroundWorker : Component
39 #else
40 public class BackgroundWorker
41 #endif
43 public BackgroundWorker ()
47 AsyncOperation async;
48 bool cancel_pending, report_progress = false, support_cancel = false, complete = false;
50 public event DoWorkEventHandler DoWork;
51 public event ProgressChangedEventHandler ProgressChanged;
52 public event RunWorkerCompletedEventHandler RunWorkerCompleted;
54 #if !NET_2_1
55 [Browsable (false)]
56 #endif
57 public bool CancellationPending {
58 get { return cancel_pending; }
61 #if !NET_2_1
62 [Browsable (false)]
63 #endif
64 public bool IsBusy {
65 get { return async != null; }
68 [DefaultValue (false)]
69 public bool WorkerReportsProgress {
70 get { return report_progress; }
71 set { report_progress = value; }
74 [DefaultValue (false)]
75 public bool WorkerSupportsCancellation {
76 get { return support_cancel; }
77 set { support_cancel = value; }
80 public void CancelAsync ()
82 if (!support_cancel)
83 throw new InvalidOperationException ("This background worker does not support cancellation.");
85 if (!IsBusy)
86 return;
88 cancel_pending = true;
91 public void ReportProgress (int percentProgress)
93 ReportProgress (percentProgress, null);
96 public void ReportProgress (int percentProgress, object userState)
98 if (!WorkerReportsProgress)
99 throw new InvalidOperationException ("This background worker does not report progress.");
101 if (complete)
102 throw new InvalidOperationException ("The background worker has ended.");
104 ProgressChangedEventArgs pcea = new ProgressChangedEventArgs (percentProgress, userState);
105 if (async == null) {
106 // we can report progress before a call to RunWorkerAsync - but we do it sync
107 OnProgressChanged (pcea);
108 } else {
109 async.Post (delegate (object o) {
110 ProgressChangedEventArgs e = o as ProgressChangedEventArgs;
111 OnProgressChanged (e);
112 }, pcea);
116 public void RunWorkerAsync ()
118 RunWorkerAsync (null);
121 delegate void ProcessWorkerEventHandler (object argument, AsyncOperation async, SendOrPostCallback callback);
123 void ProcessWorker (object argument, AsyncOperation async, SendOrPostCallback callback)
125 // do worker
126 Exception error = null;
127 DoWorkEventArgs e = new DoWorkEventArgs (argument);
128 try {
129 OnDoWork (e);
130 } catch (Exception ex) {
131 error = ex;
132 e.Cancel = false;
134 callback (new object [] {
135 new RunWorkerCompletedEventArgs (
136 e.Result, error, e.Cancel),
137 async});
140 void CompleteWorker (object state)
142 object [] args = (object []) state;
143 RunWorkerCompletedEventArgs e =
144 args [0] as RunWorkerCompletedEventArgs;
145 AsyncOperation async = args [1] as AsyncOperation;
147 SendOrPostCallback callback = delegate (object darg) {
148 this.async = null;
149 complete = true;
150 OnRunWorkerCompleted (darg as RunWorkerCompletedEventArgs);
153 async.PostOperationCompleted (callback, e);
155 cancel_pending = false;
158 public void RunWorkerAsync (object argument)
160 if (IsBusy)
161 throw new InvalidOperationException ("The background worker is busy.");
163 async = AsyncOperationManager.CreateOperation (this);
165 complete = false;
166 ProcessWorkerEventHandler handler =
167 new ProcessWorkerEventHandler (ProcessWorker);
168 handler.BeginInvoke (argument, async, CompleteWorker, null, null);
171 protected virtual void OnDoWork (DoWorkEventArgs e)
173 if (DoWork != null)
174 DoWork (this, e);
177 protected virtual void OnProgressChanged (ProgressChangedEventArgs e)
179 if (ProgressChanged != null)
180 ProgressChanged (this, e);
183 protected virtual void OnRunWorkerCompleted (RunWorkerCompletedEventArgs e)
185 if (RunWorkerCompleted != null)
186 RunWorkerCompleted (this, e);
190 #endif