C# 委托 回调 操作UI主线程 学习笔记

来源:互联网 发布:如何参加淘宝天天特价 编辑:程序博客网 时间:2024/06/06 19:13

本篇相当于是对前面两篇博的一个简单总结,相当于为c#开发桌面程序有了一个多线程的应用方案。涉及了委托传参,回调委托,跨线程等。下面先直接上代码:
这段代码实现了,点Start按钮,开始更新进度条,当进度条走到100的时候,停止,在进度条更新中,任意时刻点击Stop,停止,大致界面是这样的:
这里写图片描述

    public partial class Form1 : Form    {        private bool threadFlag = false;        private delegate void Process(object iObject);        private delegate void SetProgress(int progress);        private delegate void SetText(string progress);        private delegate void Process2(string message);        public Form1()        {            InitializeComponent();            progressBar1.Maximum = 100;        }        private void btnStart_Click(object sender, EventArgs e)        {            object testParams=new object();            threadFlag = true;            Process p = new Process(progressBarIncrease);            IAsyncResult iar = p.BeginInvoke(testParams, null, null);        }        private void btnStop_Click(object sender, EventArgs e)        {            threadFlag = false;        }        private void progressBarIncrease(object iObject)        {            int progress = 0;            while (true==threadFlag && progress<100)            {                Thread.Sleep(50);                progress++;                //修改主界面代码                updateProgressBar(progress);                updateSat(progress.ToString());            }            Process2 cbd = new Process2(progressBarIncreaseEnd);            cbd("progressBarIncrease Delegate has been Done");        }        private void progressBarIncreaseEnd(string message)        {            MessageBox.Show(message);        }        private void updateProgressBar(int progress)        {            if (true == progressBar1.InvokeRequired)            {                SetProgress sp = new SetProgress(updateProgressBar);                this.Invoke(sp, new object[] {progress});            }            else            {                progressBar1.Value = progress;            }        }        private void updateSat(string progress)        {            if (true == txtSat.InvokeRequired)            {                SetText sp = new SetText(updateSat);                this.Invoke(sp, new object[] { progress });            }            else            {                txtSat.Text =progress+"\r\n"+txtSat.Text;            }        }    }

这段代码所代表的情况几乎是所有桌面程序都会遇到的情况,很多童鞋包括我在内,都不太明白,都是照着写,其实用一个流程就可以很清楚的交代出来:

这里写图片描述

似乎也没有太清楚,anyway,主要想说明,个人认为,委托可以理解为函数指针,只是把某一个方法或者函数的地址交给了委托,而当你开启委托异步执行的时候,委托会找到这个函数的地址,然后新开一个线程去执行(应该是放入了ThreadPool中)。执行完成后,会自动处理,你并不需要关心。但常常我们想控制这个子线程的执行,要么
1.等它自己执行完。
2.你可以用上一篇中的ManualResetEvent。但是要注意在子线程中使用,要不然会阻塞主线程,导致UI卡死(其实和1差不多)
3.引入flag等标志量,这样你就可以从UI线程中去中断这个子线程(类似我们这个demo中的threadFlag)。

另外还要注意任意一个子线程操作UI一定要使用委托来实现,要不然肯定是会出现跨线程错误,切记。

1 0