c#多線程通信之委托事件
在研究c# 線程之間通信時,發(fā)現(xiàn)傳統(tǒng)的方法大概有三種:
- 全局變量,由于同一進程下的多個進程之間共享數(shù)據(jù)空間,所以使用全局變量是最簡單的方法,但要記住使用volatile進行限制。
- 線程之間發(fā)送消息(這個隨后文章中會討論到)。
- CEvent為MFC中的一個對象,可以通過對CEvent的觸發(fā)狀態(tài)進行改變,從而實現(xiàn)線程間的通信和同步,這個主要是實現(xiàn)線程直接同步的一種方法。
本文介紹的一種方法是這三種之外的一種方法,本文中實例是通過創(chuàng)建一個線程類,通過委托事件把值傳送到Form所在的類中,同時更新Form類中的一個控件(Label)中的值。
實現(xiàn)功能比較簡單,目的是實現(xiàn)此功能,先把代碼貼上:
MyThread.cs
using System;
using System.Threading;
namespace ThreadsComm
{
public delegate void ReadParamEventHandler(string sParam);
class MyThread
{
public Thread thread1;
private static ReadParamEventHandler OnReadParamEvent;
public MyThread()
{
thread1 = new Thread(new ThreadStart(MyRead));
thread1.IsBackground = true;
thread1.Start();
}
public event ReadParamEventHandler ReadParam
{
add { OnReadParamEvent += new ReadParamEventHandler(value);}
remove{ OnReadParamEvent -= new ReadParamEventHandler(value);}
}
protected void MyRead()
{
int i = 0;
while (true)
{
Thread.Sleep(1000);
i = i + 1;
OnReadParamEvent(i.ToString());//觸發(fā)事件
}
}
}
}
其中的
public event ReadParamEventHandler ReadParam
{
add { OnReadParamEvent += new ReadParamEventHandler(value);}
remove{ OnReadParamEvent -= new ReadParamEventHandler(value);}
}
這個需要說明一下:
add 上下文關鍵字用于定義一個自定義事件訪問器,當客戶端代碼訂閱您的事件時將調(diào)用該訪問器。 如果提供自定義 add 訪問器,還必須提供 remove 訪問器。
remove 上下文關鍵字用于定義一個自定義事件訪問器,當客戶端代碼取消訂閱事件時將調(diào)用該訪問器。 如果提供自定義 remove 訪問器,還必須提供 add 訪問器。
Form.cs
using System;
using System.Windows.Forms;
namespace ThreadsComm
{
public partial class Form1 : Form
{
private static string param = "";
public Form1()
{
InitializeComponent();
MyThread thread1 = new MyThread();
thread1.ReadParam += this.OnRead;
}
private void OnRead(string sParam)
{
param = sParam;
Object[] list = { this,System.EventArgs.Empty};
this.lblShow.BeginInvoke(new EventHandler(LabelShow), list);
}
protected void LabelShow(Object o, EventArgs e)
{
this.lblShow.Text = param;
}
}
}
其中的
MyThread thread1 = new MyThread(); thread1.ReadParam += this.OnRead;
是訂閱線程類中的事件。
this.lblShow.BeginInvoke(new EventHandler(LabelShow), list);
Invoke或者 BeginInvoke方法都需要一個委托對象作為參數(shù)。委托類似于回調(diào)函數(shù)的地址,因此調(diào)用者通過這兩個方法就可以把需要調(diào)用的函數(shù)地址封送給界面線程。這些方法里面如果包含了更改控件狀態(tài)的代碼,那么由于最終執(zhí)行這個方法的是界面線程,從而避免了競爭條件,避免了不可預料的問題。如果其它線程直接操作界面線程所屬的控件,那么將會產(chǎn)生競爭條件,造成不可預料的結(jié)果。
使用 Invoke完成一個委托方法的封送,就類似于使用 SendMessage方法來給界面線程發(fā)送消息,是一個同步方法。也就是說在 Invoke封送的方法被執(zhí)行完畢前, Invoke方法不會返回,從而調(diào)用者線程將被阻塞。
使用 BeginInvoke方法封送一個委托方法,類似于使用 PostMessage進行通信,這是一個異步方法。也就是該方法封送完畢后馬上返回,不會等待委托方法的執(zhí)行結(jié)束,調(diào)用者線程將不會被阻塞。但是調(diào)用者也可以使用 EndInvoke方法或者其它類似 WaitHandle機制等待異步操作的完成。
但是在內(nèi)部實現(xiàn)上, Invoke和 BeginInvoke都是用了 PostMessage方法,從而避免了 SendMessage帶來的問題。而 Invoke方法的同步阻塞是靠 WaitHandle機制來完成的。
想實驗的讀者可以建一個winform工程,采用上邊的代碼試驗一下。
以上就是c#多線程通信之委托事件的詳細內(nèi)容,更多關于c#多線程委托事件的資料請關注腳本之家其它相關文章!
相關文章
c# socket心跳超時檢測的思路(適用于超大量TCP連接情況下)
這篇文章主要介紹了c# socket心跳超時檢測的思路(適用于超大量TCP連接情況下),幫助大家更好的理解和學習使用c#,感興趣的朋友可以了解下2021-03-03
DevExpress實現(xiàn)GridView當無數(shù)據(jù)行時提示消息
這篇文章主要介紹了DevExpress實現(xiàn)GridView當無數(shù)據(jù)行時提示消息,需要的朋友可以參考下2014-08-08
給c#添加SetTimeout和SetInterval函數(shù)
Javascript中的SetTimeout和SetInterval函數(shù)很方便,把他們移植到c#中來。2008-03-03

