Roger Luo

超越梦想一起飞
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C#UI多线程编程入门

Posted on 2012-12-23 15:47  Roger Luo  阅读(356)  评论(0编辑  收藏  举报

WinForm异步编程

启动异步线程

假定form中具有如下控件一个lable(lblStatus)和一个button(btnStart),并给button添加click事件。


实现异步更新方法一:

        private void StatusAppend(string val)
        {
            this.lblStatus.Text += val;
        }

        private void SecondlyUpdate(object obj)
        {
            int _n = (int)obj;
            if (_n > 0 )
            {
                for (int i = 0; i < _n; i++)
                {
                    Thread.Sleep(1000);
                    if (this.lblStatus.InvokeRequired == true)
                        this.lblStatus.BeginInvoke(new Append(StatusAppend), new string[] { string.Format("{0},", i+1) });
                    else
                        this.lblStatus.Text += string.Format("{0}, ", i);
                }
                MessageBox.Show("Done");
            }
            return;
        }

        private delegate void Async(object obj);
        private delegate void Append(string str);

        
        private void btnStart_Click(object sender, EventArgs e)
        {
            new Async(SecondlyUpdate).BeginInvoke(3, null, null);
        }

实现异步更新方法二:

修改btnStart_Click函数实现为如下:

        private void btnStart_Click(object sender, EventArgs e)
        {
            new Thread(() =>
                {
                    int i = 0;
                    while (i++ < 5)
                    {
                        Thread.Sleep(1000);
                        this.lblStatus.BeginInvoke(new Append(StatusAppend), new string[] { string.Format("{0}, ", i) });
                    }
                }).Start();
        }
最后结果输出结果为

停止异步线程

进一步增加难度,将给form再添加一个button(btnStop)来停止异步线程与其click事件,form如下所示。

修改代码如下所示

        private Thread _t = null;
        private void btnStart_Click(object sender, EventArgs e)
        {
            _t = new Thread(() =>
                {
                    int i = 0;
                    while (i++ < 5)
                    {
                        Thread.Sleep(1000);
                        if (this.lblStatus.InvokeRequired == true)
                            this.lblStatus.BeginInvoke(new Append(StatusAppend), new string[] { string.Format("{0}, ", i) });
                        else
                            this.lblStatus.Text += string.Format("{0}, ", i);
                    }
                    if (this.btnStop.InvokeRequired == true)
                    {
                        this.btnStop.BeginInvoke((MethodInvoker)delegate() {
                            this.btnStop.Enabled = false;
                        }, null);
                    }
                    if (this.btnStart.InvokeRequired == true)
                    {
                        //this.btnStart.BeginInvoke((MethodInvoker)delegate()
                        //{
                        //    this.btnStart.Enabled = true;
                        //}, null);
                        this.btnStart.BeginInvoke(new Action<int>(delegate(int parm){
                            this.btnStart.Enabled = true;
                        }), 1);
                    }
                });
            _t.IsBackground = true;
            _t.Start();
            btnStart.Enabled = false;
            btnStop.Enabled = true;
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            if (_t != null)
            {
                if (_t.IsAlive == true)
                {
                    _t.Abort();
                    lblStatus.Text = "Status: ";
                    btnStop.Enabled = false;
                    btnStart.Enabled = true;
                }
            }
        }
其中添加了Thread成员变量来存储Thread对象以便在stop按钮click事件中调用abort来终止异步线程;

同时在修改了Thread中ThreadStart函数(已经匿名了),后面修改start/stop按钮的属性,同时使用了MethodInvoker以及Action来简化代码,否则需要写额外的函数以及delegate。

在stop按钮中click事件里,通过thread对象的IsAlive属性来调用Abort函数终止代码。

全文代码: 下载