如果在C# WinForm开发多线程程序,多线程中的方法不能直接更新主线程上的对象(比如UI),但可以通过委托和事件更新主线程上的对象。源代码下载http://download.csdn.net/detail/kmblack1/4909697,示例如下:
代码如下:适应所有.net版本
using System;
using System.Threading;
using System.ComponentModel;
namespace WindowsFormsApplication1
{
public interface IAsyncEventArgs
{
int action { get; }
object[] getObjects { get; }
}
/// <summary>
/// 线程事件参数
/// </summary>
internal class AsyncEventArgs : EventArgs, IAsyncEventArgs
{
private readonly int m_action;
private readonly object[] m_objects;
public int action
{
get { return this.m_action; }
}
public object[] getObjects
{
get { return this.m_objects; }
}
public AsyncEventArgs(int action, object[] objs)
{
this.m_action = action;
this.m_objects = objs;
}
}
/// <summary>
/// 异步操作基类,基类不需要修改,任务应该在子类中完成
/// 注意:只适用用winform开发
/// </summary>
public abstract class AsyncBase
{
private Thread m_thread;
private readonly ISynchronizeInvoke m_Target;
private bool m_IsStop = false;
private bool[] m_isCancelFlag = new bool[]{false,false};
protected int m_action = 0;
public event EventHandler TaskBefore;
public event EventHandler TaskProgress;
public event EventHandler TaskDone;
public event EventHandler Complete;
public event EventHandler Error;
//开始执行任务之前
private void OnTaskBefore(object sender)
{
toTarget(TaskBefore, new object[] { sender, new AsyncEventArgs(this.m_action, null) });
}
//执行任务进度
protected void OnTaskProgress(object sender, int step)
{
toTarget(TaskProgress, new object[] { sender, new AsyncEventArgs(this.m_action, new object[] { step }) });
}
//执行任务成功完成(只有任务成功才会执行,取消和异常均不会执行),传递给主线程的对象在这里设置
protected void OnTaskDone(object sender, object[] objs)
{
toTarget(TaskDone, new object[] { sender, new AsyncEventArgs(this.m_action, objs) });
}
//执行任务时发生异常
private void OnError(object sender, Exception exp)
{
toTarget(Error, new object[] { sender, new AsyncEventArgs(this.m_action, new object[] { exp }) });
}
//完成一个任务,无论如果都会执行
private void OnComplete(object sender)
{
toTarget(Complete, new object[] { sender, new AsyncEventArgs(this.m_action, null) });
}
/// <summary>
/// 构造方法
/// </summary>
/// <param name="Target">调用目标</param>
protected AsyncBase(ISynchronizeInvoke target)
{
this.m_Target = target;
this.m_thread = null;
}
~AsyncBase()
{
Stop();
}
//启动一个工作线程
public void Start()
{
try
{
this.m_thread = new Thread(new ThreadStart(Work));
this.m_thread.Start();
}
catch (Exception e)
{
this.m_thread = null;
throw e;
}// catch
Monitor.Enter(this);
Monitor.Wait(this);
Monitor.Exit(this);
}// end void
//停止一个工作线程
public void Stop()
{
if (null == this.m_thread)
return;
/*取消并等待任务完成*/
Monitor.Enter(this);
if (this.m_isCancelFlag[1])
{
this.m_isCancelFlag[0] = true;
Monitor.Wait(this);
}
Monitor.Exit(this);
/*停止并等待任务完成*/
Monitor.Enter(this);
this.m_IsStop = true;
Monitor.Pulse(this);
Monitor.Exit(this);
this.m_thread.Join();
Monitor.Enter(this);
this.m_isCancelFlag[0] = false;
this.m_isCancelFlag[1] = false;
this.m_IsStop = false;
Monitor.Exit(this);
this.m_thread = null;
}
//取消一个支持取消功能的任务(必须支持取消功能)
public void cnacelTask()
{
Monitor.Enter(this);
this.m_isCancelFlag[0] = true;
Monitor.Exit(this);
}
/// <summary>
/// 工作方法
/// </summary>
private void Work()
{
bool isStop = false;
Monitor.Enter(this); //lock
Monitor.Pulse(this); //send signal thread start
while (!isStop)
{
Monitor.Wait(this); //wait task and unlock
//lock
this.m_isCancelFlag[0] = false;
this.m_isCancelFlag[1] = false;
isStop = this.m_IsStop;
if (!isStop)
Workex();
}
Monitor.Exit(this); //unlock
}// end void
//工作方法
private void Workex()
{
try
{
OnTaskBefore(this);
AsyncWork();
}
catch (Exception e)
{
OnError(this, e);
}// catch
finally
{
this.m_isCancelFlag[0] = false;
this.m_isCancelFlag[1] = false;
this.m_action = 0;
Monitor.Pulse(this);
OnComplete(this);
}// end finally
}
//实现多线程任务
protected abstract void AsyncWork();
//在子类中调用,获取可以取消的任务是否取消
protected bool isCnacel()
{
if ( !this.m_isCancelFlag[1])
this.m_isCancelFlag[1] = true;
bool is_cnacel = this.m_isCancelFlag[0];
Monitor.Exit(this);
Monitor.Enter(this);
return is_cnacel;
}
//回到主线程上执行委托
private void toTarget(Delegate dlg, params object[] paras)
{
if (this.m_Target != null)
{
if (dlg != null)
this.m_Target.BeginInvoke(dlg, paras);
}
else
{
throw new Exception("在线程运行结束之前,调用目标已经关闭,调用目标必须等待线程运行完成后才能关闭!");
}
}
}
}
using System;
using System.ComponentModel;
using System.Threading;
namespace WindowsFormsApplication1
{
class AsyncImport : AsyncBase
{
private string m_filename;
public AsyncImport(ISynchronizeInvoke target)
: base(target)
{
this.m_filename = string.Empty;
}
//在线程中执行任务,任务id为1
public void import(string filename)
{
Monitor.Enter(this);
if( 0 != this.m_action)
Monitor.Wait(this);
this.m_filename = filename;
this.m_action = 1;
Monitor.Pulse(this);
Monitor.Exit(this);
}
//在线程中执行任务,任务id为2
public void importEx(string filename)
{
Monitor.Enter(this);
if (0 != this.m_action)
Monitor.Wait(this);
this.m_filename = filename;
this.m_action = 2;
Monitor.Pulse(this);
Monitor.Exit(this);
}
//根据任务ID执行任务
protected override void AsyncWork()
{
switch (this.m_action)
{
case 1:
thrImportFile(this.m_filename);
break;
case 2:
thrImportFileEx(this.m_filename);
break;
}
}
//已知任务步骤,任务可以取消
private void thrImportFile(string filename)
{
bool is_cancel = false;
for (int i = 0; i < 100; ++i)
{
//调用基类的方法检查任务是否取消
is_cancel = isCnacel();
if (is_cancel)
break;
System.Threading.Thread.Sleep(100);
OnTaskProgress(this, i);
}
if (!is_cancel)
OnTaskDone(this, null);
}
//不确定任务完成步骤,任务不可以取消
private void thrImportFileEx(string filename)
{
System.Threading.Thread.Sleep(10000);
//在这里传递任务完成后传递给主线程的对象
OnTaskDone(this, new object[]{"OK"});
}
}
}
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
//AsyncImport对象必须在Form::Dispose中停止
//否则会抛出异常 “在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。”
private AsyncImport m_AsyncImport;
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
//停止工作线程
this.m_AsyncImport.Stop();
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
protected override void OnLoad(EventArgs e)
{
try
{
//this.btnCancel.Enabled = false;
this.m_AsyncImport = new AsyncImport(this);
this.m_AsyncImport.TaskBefore += new EventHandler(AsyncImport_TaskBefore);
this.m_AsyncImport.TaskProgress += new EventHandler(AsyncImport_TaskProgress);
this.m_AsyncImport.TaskDone += new EventHandler(AsyncImport_TaskDone);
this.m_AsyncImport.Error += new EventHandler(AsyncImport_Error);
this.m_AsyncImport.Complete += new EventHandler(AsyncImport_Complete);
//在窗体创建时同时运行工作线程,并在窗体Dispose方法中停止工作线程
this.m_AsyncImport.Start();
base.OnLoad(e);
}
catch (Exception exp)
{
MessageBox.Show(this, exp.Message, "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit();
}
}
//在实际运行中应该在任务开始前控制窗体状态
private void EnableAll(bool isEnable)
{
this.ControlBox = isEnable;
this.btnTask1.Enabled = isEnable;
this.btnTask2.Enabled = isEnable;
this.btnCancel.Enabled = !isEnable;
}
void AsyncImport_TaskBefore(object sender, EventArgs e)
{
//EnableAll(false);
IAsyncEventArgs pAsyncEventArgs = e as IAsyncEventArgs;
switch (pAsyncEventArgs.action)
{
case 1:
this.progressBar1.Minimum = 0;
this.progressBar1.Maximum = 100;
this.progressBar1.Step = 1;
this.progressBar1.Value = 0;
this.progressBar1.Style = ProgressBarStyle.Blocks;
break;
case 2:
this.progressBar1.Style = ProgressBarStyle.Marquee;
break;
}
}
void AsyncImport_TaskProgress(object sender, EventArgs e)
{
IAsyncEventArgs pAsyncEventArgs = e as IAsyncEventArgs;
switch (pAsyncEventArgs.action)
{
case 1:
int step = (int)pAsyncEventArgs.getObjects[0];
this.progressBar1.Value = ++step;
break;
case 2:
break;
}
}
void AsyncImport_TaskDone(object sender, EventArgs e)
{
//throw new NotImplementedException();
IAsyncEventArgs pAsyncEventArgs = e as IAsyncEventArgs;
switch (pAsyncEventArgs.action)
{
case 1:
break;
case 2:
MessageBox.Show(this, pAsyncEventArgs.getObjects[0] as string, "msg", MessageBoxButtons.OK, MessageBoxIcon.Information);
break;
}
}
void AsyncImport_Error(object sender, EventArgs e)
{
IAsyncEventArgs pAsyncEventArgs = e as IAsyncEventArgs;
Exception exp = pAsyncEventArgs.getObjects[0] as Exception;
MessageBox.Show(this, exp.Message, "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
void AsyncImport_Complete(object sender, EventArgs e)
{
//EnableAll(true);
if (ProgressBarStyle.Marquee == this.progressBar1.Style)
this.progressBar1.Style = ProgressBarStyle.Blocks;
}
//如果在执行任务2时同时点击任务1按钮,任务2继续执行,
//任务1等待任务2执行完成后执行,由于处于等待状态,主界面将无法响应,直到任务1开始执行
//如果任务1正在执行,直接关闭窗体时,将取消任务1执行,并关闭窗体
private void btnTask1_Click(object sender, EventArgs e)
{
this.m_AsyncImport.import("");
}
//如果在执行任务1时同时点击任务2按钮,任务1继续执行,
//任务2等待任务1执行完成后执行,由于处于等待状态,主界面将无法响应,直到任务2开始执行
//如果任务2正在执行,直接关闭窗体时,由于任务2不支持取消功能,主界面将处于等待状态,直到任务2执行完成后关闭窗体
private void btnTask2_Click(object sender, EventArgs e)
{
this.m_AsyncImport.importEx("");
}
private void btnCancel_Click(object sender, EventArgs e)
{
//注意示例中的任务2不能取消,在运行任务2时如果点击取消按钮,将处于等待状态,主界面将无法响应,直到任务2运行完成
this.m_AsyncImport.cnacelTask();
}
}
}