在.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