a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
189 lines
5.0 KiB
C#
189 lines
5.0 KiB
C#
//
|
|
// BackgroundWorker.cs
|
|
//
|
|
// Authors:
|
|
// Atsushi Enomoto <atsushi@ximian.com>
|
|
//
|
|
// Copyright (C) 2006 Novell, Inc.
|
|
//
|
|
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
|
|
namespace System.ComponentModel
|
|
{
|
|
#if !NET_2_1
|
|
[DefaultEvent ("DoWork")]
|
|
public class BackgroundWorker : Component
|
|
#else
|
|
public class BackgroundWorker
|
|
#endif
|
|
{
|
|
public BackgroundWorker ()
|
|
{
|
|
}
|
|
|
|
AsyncOperation async;
|
|
bool cancel_pending, report_progress = false, support_cancel = false, complete = false;
|
|
|
|
public event DoWorkEventHandler DoWork;
|
|
public event ProgressChangedEventHandler ProgressChanged;
|
|
public event RunWorkerCompletedEventHandler RunWorkerCompleted;
|
|
|
|
#if !NET_2_1
|
|
[Browsable (false)]
|
|
#endif
|
|
public bool CancellationPending {
|
|
get { return cancel_pending; }
|
|
}
|
|
|
|
#if !NET_2_1
|
|
[Browsable (false)]
|
|
#endif
|
|
public bool IsBusy {
|
|
get { return async != null; }
|
|
}
|
|
|
|
[DefaultValue (false)]
|
|
public bool WorkerReportsProgress {
|
|
get { return report_progress; }
|
|
set { report_progress = value; }
|
|
}
|
|
|
|
[DefaultValue (false)]
|
|
public bool WorkerSupportsCancellation {
|
|
get { return support_cancel; }
|
|
set { support_cancel = value; }
|
|
}
|
|
|
|
public void CancelAsync ()
|
|
{
|
|
if (!support_cancel)
|
|
throw new InvalidOperationException ("This background worker does not support cancellation.");
|
|
|
|
if (!IsBusy)
|
|
return;
|
|
|
|
cancel_pending = true;
|
|
}
|
|
|
|
public void ReportProgress (int percentProgress)
|
|
{
|
|
ReportProgress (percentProgress, null);
|
|
}
|
|
|
|
public void ReportProgress (int percentProgress, object userState)
|
|
{
|
|
if (!WorkerReportsProgress)
|
|
throw new InvalidOperationException ("This background worker does not report progress.");
|
|
|
|
if (complete)
|
|
throw new InvalidOperationException ("The background worker has ended.");
|
|
|
|
ProgressChangedEventArgs pcea = new ProgressChangedEventArgs (percentProgress, userState);
|
|
if (async == null) {
|
|
// we can report progress before a call to RunWorkerAsync - but we do it sync
|
|
OnProgressChanged (pcea);
|
|
} else {
|
|
async.Post (delegate (object o) {
|
|
ProgressChangedEventArgs e = o as ProgressChangedEventArgs;
|
|
OnProgressChanged (e);
|
|
}, pcea);
|
|
}
|
|
}
|
|
|
|
public void RunWorkerAsync ()
|
|
{
|
|
RunWorkerAsync (null);
|
|
}
|
|
|
|
delegate void ProcessWorkerEventHandler (object argument, AsyncOperation async, SendOrPostCallback callback);
|
|
|
|
void ProcessWorker (object argument, AsyncOperation async, SendOrPostCallback callback)
|
|
{
|
|
// do worker
|
|
Exception error = null;
|
|
DoWorkEventArgs e = new DoWorkEventArgs (argument);
|
|
try {
|
|
OnDoWork (e);
|
|
} catch (Exception ex) {
|
|
error = ex;
|
|
e.Cancel = false;
|
|
}
|
|
callback (new object [] {
|
|
new RunWorkerCompletedEventArgs (
|
|
e.Result, error, e.Cancel),
|
|
async});
|
|
}
|
|
|
|
void CompleteWorker (object state)
|
|
{
|
|
object [] args = (object []) state;
|
|
RunWorkerCompletedEventArgs e =
|
|
args [0] as RunWorkerCompletedEventArgs;
|
|
AsyncOperation async = args [1] as AsyncOperation;
|
|
|
|
SendOrPostCallback callback = delegate (object darg) {
|
|
this.async = null;
|
|
complete = true;
|
|
OnRunWorkerCompleted (darg as RunWorkerCompletedEventArgs);
|
|
};
|
|
|
|
async.PostOperationCompleted (callback, e);
|
|
|
|
cancel_pending = false;
|
|
}
|
|
|
|
public void RunWorkerAsync (object argument)
|
|
{
|
|
if (IsBusy)
|
|
throw new InvalidOperationException ("The background worker is busy.");
|
|
|
|
async = AsyncOperationManager.CreateOperation (this);
|
|
|
|
complete = false;
|
|
ProcessWorkerEventHandler handler =
|
|
new ProcessWorkerEventHandler (ProcessWorker);
|
|
handler.BeginInvoke (argument, async, CompleteWorker, null, null);
|
|
}
|
|
|
|
protected virtual void OnDoWork (DoWorkEventArgs e)
|
|
{
|
|
if (DoWork != null)
|
|
DoWork (this, e);
|
|
}
|
|
|
|
protected virtual void OnProgressChanged (ProgressChangedEventArgs e)
|
|
{
|
|
if (ProgressChanged != null)
|
|
ProgressChanged (this, e);
|
|
}
|
|
|
|
protected virtual void OnRunWorkerCompleted (RunWorkerCompletedEventArgs e)
|
|
{
|
|
if (RunWorkerCompleted != null)
|
|
RunWorkerCompleted (this, e);
|
|
}
|
|
}
|
|
}
|