C# WinForm 多线程 基类

如果在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();
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kmblack1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值