Implement TypeDescriptor.InterfaceType.
[mono.git] / mcs / class / System / System.ComponentModel / BackgroundWorker.cs
1 //
2 // BackgroundWorker.cs
3 //
4 // Authors:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2006 Novell, Inc.
8 //
9
10 //
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.
29 //
30 #if NET_2_0
31 using System.Collections.Generic;
32 using System.Threading;
33
34 namespace System.ComponentModel
35 {
36 #if !NET_2_1
37         [DefaultEvent ("DoWork")]
38         public class BackgroundWorker : Component
39 #else
40         public class BackgroundWorker
41 #endif
42         {
43                 public BackgroundWorker ()
44                 {
45                 }
46
47                 AsyncOperation async;
48                 bool cancel_pending, report_progress = false, support_cancel = false, complete = false;
49
50                 public event DoWorkEventHandler DoWork;
51                 public event ProgressChangedEventHandler ProgressChanged;
52                 public event RunWorkerCompletedEventHandler RunWorkerCompleted;
53
54 #if !NET_2_1
55                 [Browsable (false)]
56 #endif
57                 public bool CancellationPending {
58                         get { return cancel_pending; }
59                 }
60
61 #if !NET_2_1
62                 [Browsable (false)]
63 #endif
64                 public bool IsBusy {
65                         get { return async != null; }
66                 }
67
68                 [DefaultValue (false)]
69                 public bool WorkerReportsProgress {
70                         get { return report_progress; }
71                         set { report_progress = value; }
72                 }
73
74                 [DefaultValue (false)]
75                 public bool WorkerSupportsCancellation {
76                         get { return support_cancel; }
77                         set { support_cancel = value; }
78                 }
79
80                 public void CancelAsync ()
81                 {
82                         if (!support_cancel)
83                                 throw new InvalidOperationException ("This background worker does not support cancellation.");
84
85                         if (!IsBusy)
86                                 return;
87
88                         cancel_pending = true;
89                 }
90
91                 public void ReportProgress (int percentProgress)
92                 {
93                         ReportProgress (percentProgress, null);
94                 }
95
96                 public void ReportProgress (int percentProgress, object userState)
97                 {
98                         if (!WorkerReportsProgress)
99                                 throw new InvalidOperationException ("This background worker does not report progress.");
100
101                         if (complete)
102                                 throw new InvalidOperationException ("The background worker has ended.");
103
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);
113                         }
114                 }
115
116                 public void RunWorkerAsync ()
117                 {
118                         RunWorkerAsync (null);
119                 }
120
121                 delegate void ProcessWorkerEventHandler (object argument, AsyncOperation async, SendOrPostCallback callback);
122
123                 void ProcessWorker (object argument, AsyncOperation async, SendOrPostCallback callback)
124                 {
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;
133                         }
134                         callback (new object [] {
135                                 new RunWorkerCompletedEventArgs (
136                                         e.Result, error, e.Cancel),
137                                 async});
138                 }
139
140                 void CompleteWorker (object state)
141                 {
142                         object [] args = (object []) state;
143                         RunWorkerCompletedEventArgs e =
144                                 args [0] as RunWorkerCompletedEventArgs;
145                         AsyncOperation async = args [1] as AsyncOperation;
146
147                         SendOrPostCallback callback = delegate (object darg) {
148                                 this.async = null;
149                                 complete = true;
150                                 OnRunWorkerCompleted (darg as RunWorkerCompletedEventArgs);
151                         };
152
153                         async.PostOperationCompleted (callback, e);
154
155                         cancel_pending = false;
156                 }
157
158                 public void RunWorkerAsync (object argument)
159                 {
160                         if (IsBusy)
161                                 throw new InvalidOperationException ("The background worker is busy.");
162
163                         async = AsyncOperationManager.CreateOperation (this);
164
165                         complete = false;
166                         ProcessWorkerEventHandler handler =
167                                 new ProcessWorkerEventHandler (ProcessWorker);
168                         handler.BeginInvoke (argument, async, CompleteWorker, null, null);
169                 }
170
171                 protected virtual void OnDoWork (DoWorkEventArgs e)
172                 {
173                         if (DoWork != null)
174                                 DoWork (this, e);
175                 }
176
177                 protected virtual void OnProgressChanged (ProgressChangedEventArgs e)
178                 {
179                         if (ProgressChanged != null)
180                                 ProgressChanged (this, e);
181                 }
182
183                 protected virtual void OnRunWorkerCompleted (RunWorkerCompletedEventArgs e)
184                 {
185                         if (RunWorkerCompleted != null)
186                                 RunWorkerCompleted (this, e);
187                 }
188         }
189 }
190 #endif