源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

c# winform多线程的小例子

  • 时间:2022-02-24 03:57 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:c# winform多线程的小例子
[img]http://files.jb51.net/file_images/article/201304/2013414103213275.png[/img] 在文本框中输入一个数字,点击开始累加按钮,程序计算从1开始累计到该数字的结果。因为该累加过程比较耗时,如果直接在UI线程中进行,那么当前窗口将出现假死。为了有更好的用户体验,程序启动一个新的线程来单独执行该计算,然后每隔200毫秒读取一次累加结果,并把结果显示到文本框下方的label控件中。同时,程序支持取消操作,点击取消累计按钮,程序将取消累加操作,并把当前累加值显示到label中。为了方便后面的描述,我把UI线程称作主线程,把执行累加计算的线程称作工作者线程。该过程有两个关键点: 1:如何在工作者线程中访问主线程创建的控件; 2:如何取消比较耗时的计算; 为了便于在工作者线程中调用累加过程,我把它写成一个单独方法,如下:
[u]复制代码[/u] 代码如下:
/// <summary>         /// 从1累加到指定的值,为了让该方法支持取消操作所以需要CancellationToken参数         /// </summary>         /// <param name="countTo">累加到的指定值</param>         /// <param name="ct">取消凭证</param>         private void CountTo(int countTo, CancellationToken ct) {             int sum = 0;             for (; countTo > 0; countTo--) {                 if (ct.IsCancellationRequested) {                     break;                 }                 sum += countTo;                 //Invoke方法用于获得创建lbl_Status的线程所在的上下文                 this.Invoke(new Action(()=>lbl_Status.Text = sum.ToString()));                                Thread.Sleep(200);             }         }
该方法就是用于累加数字,它有两个需要注意的地方 1:方法需要传递一个CancellationToken参数,用于支持取消操作(《clr via c# 3版》中把这种方式称作协作式取消,也就是说某一个操作必须支持取消,然后才能取消该操作); 2:为了允许工作者线程访问主线程创建的lbl_Status控件,我在该线程中使用this.Invoke方法。该方法用于获得主线程所创建控件的访问权。它需要一个委托作为参数,在该委托中我们可以定义对lbl_Status的操作。例如在上例中我就是把当前的累加结果赋给lbl_Status的Text属性。 然后我们看一下如何在一个共走着线程中执行计算耗时的操作,也就是“开始累加”按钮的操作:
[u]复制代码[/u] 代码如下:
private void btn_Count_Click(object sender, EventArgs e)         {             _cts = new CancellationTokenSource();             ThreadPool.QueueUserWorkItem(state=>CountTo(int.Parse(txt_CountTo.Text),_cts.Token));         }
我使用线程池线程来执行该操作,之所以使用线程池线程而不是自己的Threading对象,是因为线程池默认已经为我们创建好了一些线程,从而省去创建新线程造成的一些列资源消耗,同时,完成计算任务后该线程池线程自动回到池中等待下一个任务。我把_cts作为一个成员变量,声明如下:
[u]复制代码[/u] 代码如下:
private CancellationTokenSource _cts;
它需要引入using System.Threading;命名空间。 取消操作更加简单,代码如下:
[u]复制代码[/u] 代码如下:
private void btn_Cancel_Click(object sender, EventArgs e)         {             if (_cts != null)                 _cts.Cancel();         }
这样我们就完成了在winform中使用多线程的例子,同时该例子支持取消操作。完整代码如下:
[u]复制代码[/u] 代码如下:
using System; using System.Threading; using System.Windows.Forms; namespace WinformApp {     public partial class Form1 : Form     {         private CancellationTokenSource _cts;         public Form1()         {             InitializeComponent();         }         /// <summary>         /// 从1累加到指定的值,为了让该方法支持取消操作所以需要CancellationToken参数         /// </summary>         /// <param name="countTo">累加到的指定值</param>         /// <param name="ct">取消凭证</param>         private void CountTo(int countTo, CancellationToken ct) {             int sum = 0;             for (; countTo > 0; countTo--) {                 if (ct.IsCancellationRequested) {                     break;                 }                 sum += countTo;                 //Invoke方法用于获得创建lbl_Status的线程所在的上下文                 this.Invoke(new Action(()=>lbl_Status.Text = sum.ToString()));                 Thread.Sleep(200);             }         }         private void btn_Count_Click(object sender, EventArgs e)         {             _cts = new CancellationTokenSource();             ThreadPool.QueueUserWorkItem(state=>CountTo(int.Parse(txt_CountTo.Text),_cts.Token));         }         private void btn_Cancel_Click(object sender, EventArgs e)         {             if (_cts != null)                 _cts.Cancel();         }         private void btn_Pause_Click(object sender, EventArgs e)         {         }     } }
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部