在.net compact framework中,没有BackgroundWorker,应该会让我们这些用惯了BackgroundWorker的人感到非常的不便。BackgroundWorker可以非常方便解决线程和控件之间的互操作问题,做出界面运行非常流畅的引用程序。(该组件因wince的某些特性,不能解决根本问题,建议还是用线程来解决。)
在反编译了.net framework的BackgroundWorker后,发现基本上95%以上的代码都可以直接COPY过来,唯一存在问题的就是下面这段代码:
if (this.asyncOperation != null)
{
this.asyncOperation.Post(this.progressReporter, arg);
}
else
{
this.progressReporter(arg);
}
这段代实际上要做的事情是这样的:如果执行该方法的线程和控件所在的线程不是同一个线程,就把该委托交给控件所在的线程去执行,否则就直接执行,为了实现这个操作,我做了如下的改动,在构造函数中,我这样写:
public BackgroundWorker()
{
this.threadStart = new WorkerThreadStartDelegate(this.WorkerThreadStart);
this.operationCompleted = new SendOrPostCallback(this.AsyncOperationCompleted);
this.progressReporter = new SendOrPostCallback(this.ProgressReporter);
this.Handler = Thread.CurrentThread.ManagedThreadId;
}
所以,上面的代码我做了如下的改写:
if (Thread.CurrentThread.ManagedThreadId!= this.Handler)
{
Post(this.progressReporter, arg);
}
else
{
this.progressReporter(arg);
}
Post方法的代码如下:
public virtual void Post(SendOrPostCallback d, object state)
{
if (d != null && controlToSendTo != null)
{
controlToSendTo.Invoke(d, state);
}
}
controlToSendTo 是调用该BackgroundWorker得用户控件。该BackgroundWorker得所有代码是这样的:
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace ZFB.PDA.Dao
{
public class BackgroundWorker : Component
{
private bool canCancelWorker;
private bool cancellationPending;
private static readonly object doWorkKey = new object();
private bool isRunning;
private readonly SendOrPostCallback operationCompleted;
private static readonly object progressChangedKey = new object();
private readonly SendOrPostCallback progressReporter;
private static readonly object runWorkerCompletedKey = new object();
private readonly WorkerThreadStartDelegate threadStart;
private readonly int Handler = 0;
private Control controlToSendTo = null;
/// <summary>
/// 开始后台任务
/// </summary>
public event DoWorkEventHandler DoWork
{
add
{
base.Events.AddHandler(doWorkKey, value);
}
remove
{
base.Events.RemoveHandler(doWorkKey, value);
}
}
/// <summary>
/// 后台任务执行的进度
/// </summary>
public event ProgressChangedEventHandler ProgressChanged
{
add
{
base.Events.AddHandler(progressChangedKey, value);
}
remove
{
base.Events.RemoveHandler(progressChangedKey, value);
}
}
/// <summary>
/// 后台任务完成
/// </summary>
public event RunWorkerCompletedEventHandler RunWorkerCompleted
{
add
{
base.Events.AddHandler(runWorkerCompletedKey, value);
}
remove
{
base.Events.RemoveHandler(runWorkerCompletedKey, value);
}
}
public BackgroundWorker()
{
this.threadStart = new WorkerThreadStartDelegate(this.WorkerThreadStart);
this.operationCompleted = new SendOrPostCallback(this.AsyncOperationCompleted);
this.progressReporter = new SendOrPostCallback(this.ProgressReporter);
this.Handler = Thread.CurrentThread.ManagedThreadId;
}
private void AsyncOperationCompleted(object arg)
{
this.isRunning = false;
this.cancellationPending = false;
this.OnRunWorkerCompleted((RunWorkerCompletedEventArgs)arg);
}
public void CancelAsync()
{
this.cancellationPending = true;
}
protected virtual void OnDoWork(DoWorkEventArgs e)
{
DoWorkEventHandler handler = (DoWorkEventHandler)base.Events[doWorkKey];
if (handler != null)
{
handler(this, e);
}
}
protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
{
ProgressChangedEventHandler handler = (ProgressChangedEventHandler)base.Events[progressChangedKey];
if (handler != null)
{
handler(this, e);
}
}
protected virtual void OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
{
RunWorkerCompletedEventHandler handler = (RunWorkerCompletedEventHandler)base.Events[runWorkerCompletedKey];
if (handler != null)
{
handler(this, e);
}
}
private void ProgressReporter(object arg)
{
this.OnProgressChanged((ProgressChangedEventArgs)arg);
}
public void ReportProgress(int percentProgress)
{
this.ReportProgress(percentProgress, null);
}
public void ReportProgress(int percentProgress, object userState)
{
ProgressChangedEventArgs arg = new ProgressChangedEventArgs(percentProgress, userState);
if (Thread.CurrentThread.ManagedThreadId!= this.Handler)
{
Post(this.progressReporter, arg);
}
else
{
this.progressReporter(arg);
}
}
public void RunWorkerAsync(Control ctl)
{
this.RunWorkerAsync(ctl,null);
}
public void RunWorkerAsync(Control ctl,object argument)
{
if (this.isRunning)
{
throw new InvalidOperationException("BackgroundWorker_WorkerAlreadyRunning");
}
if (ctl == null)
{
throw new Exception();
}
controlToSendTo = ctl;
this.isRunning = true;
this.cancellationPending = false;
this.threadStart.Invoke(argument);
}
private void WorkerThreadStart(object argument)
{
object result = null;
Exception error = null;
bool cancelled = false;
try
{
DoWorkEventArgs e = new DoWorkEventArgs(argument);
this.OnDoWork(e);
if (e.Cancel)
{
cancelled = true;
}
else
{
result = e.Result;
}
}
catch (Exception exception2)
{
error = exception2;
}
RunWorkerCompletedEventArgs arg = new RunWorkerCompletedEventArgs(result, error, cancelled);
if (Thread.CurrentThread.ManagedThreadId != this.Handler)
{
Post(this.operationCompleted, arg);
}
else
{
this.operationCompleted(arg);
}
}
public bool CancellationPending
{
get
{
return this.cancellationPending;
}
}
public bool IsBusy
{
get
{
return this.isRunning;
}
}
public bool WorkerSupportsCancellation
{
get
{
return this.canCancelWorker;
}
set
{
this.canCancelWorker = value;
}
}
public virtual void Post(SendOrPostCallback d, object state)
{
if (d != null && controlToSendTo != null)
{
controlToSendTo.Invoke(d, state);
}
}
private delegate void WorkerThreadStartDelegate(object argument);
public delegate void SendOrPostCallback(object state);
}
}
如果大家有更好的办法,希望大家给我留言。。。
代码下载:BackgroundWorker