c# winform多線程的小例子

來源:互聯網
上載者:User

在文字框中輸入一個數字,點擊開始累加按鈕,程式計算從1開始累計到該數位結果。因為該累加過程比較耗時,如果直接在UI線程中進行,那麼當前視窗將出現假死。為了有更好的使用者體驗,程式啟動一個新的線程來單獨執行該計算,然後每隔200毫秒讀取一次累加結果,並把結果顯示到文字框下方的label控制項中。同時,程式支援取消操作,點擊取消累計按鈕,程式將取消累加操作,並把當前累加值顯示到label中。為了方便後面的描述,我把UI線程稱作主線程,把執行累加計算的線程稱作工作者線程。該過程有兩個關鍵點:

1:如何在工作者線程中訪問主線程建立的控制項;

2:如何取消比較耗時的計算;

為了便於在工作者線程中調用累加過程,我把它寫成一個單獨方法,如下:

複製代碼 代碼如下:/// <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屬性。

然後我們看一下如何在一個共走著線程中執行計算耗時的操作,也就是“開始累加”按鈕的操作:

複製代碼 代碼如下: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作為一個成員變數,聲明如下:

複製代碼 代碼如下:private CancellationTokenSource _cts;

它需要引入using System.Threading;命名空間。

取消操作更加簡單,代碼如下:

複製代碼 代碼如下:private void btn_Cancel_Click(object sender, EventArgs e)
{
if (_cts != null)
_cts.Cancel();
}

這樣我們就完成了在winform中使用多線程的例子,同時該例子支援取消操作。完整代碼如下:

複製代碼 代碼如下: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)
{

}

}
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.