在C#中使用代理的方式觸發事件

事件(event)是一個非常重要的概念,我們的程序時刻都在觸發和接收著各種事件:鼠標點擊事件,鍵盤事件,以及處理操作系統的各種事件。所謂事件就是由某個對象發出的消息。比如用戶按下了某個按鈕,某個文件發生了改變,socket上有數據到達。觸發事件的對象稱作發送者(sender),捕獲事件并且做出響應的對象稱作接收者(receiver),一個事件可以存在多個接受者。
在異步機制中,事件是線程之間進行通信的一個非常常用的方式。比如:用戶在界面上按下一個按鈕,執行某項耗時的任務。程序此時啟動一個線程來處理這個任務,用戶界面上顯示一個進度條指示用戶任務執行的狀態。這個功能就可以使用事件來進行處理。可以將處理任務的類作為消息的發送者,任務開始時,發出“TaskStart”事件,任務進行中的不同時刻發出“TaskDoing”事件,并且攜帶參數說明任務進行的比例,任務結束的時候發出“TaskDone”事件,在畫面中接收并且處理這些事件。這樣實現了功能,并且界面和后臺執行任務的模塊耦合程度也是最低的。
具體說C#語言,事件的實現依賴于“代理”(delegate)的概念,先了解一下代理。
代理(delegate)
delegateC#中的一種類型,它實際上是一個能夠持有對某個方法的引用的類。與其它的類不同,delegate類能夠擁有一個簽名(signature),并且它只能持有與它的簽名相匹配的方法的引用。它所實現的功能與C/C++中的函數指針十分相似。它允許你傳遞一個類A的方法m給另一個類B的對象,使得類B的對象能夠調用這個方法m。但與函數指針相比,delegate有許多函數指針不具備的優點。首先,函數指針只能指向靜態函數,而delegate既可以引用靜態函數,又可以引用非靜態成員函數。在引用非靜態成員函數時,delegate不但保存了對此函數入口指針的引用,而且還保存了調用此函數的類實例的引用。其次,與函數指針相比,delegate是面向對象、類型安全、可靠的受控(managed)對象。也就是說,runtime能夠保證delegate指向一個有效的方法,你無須擔心delegate會指向無效地址或者越界地址。
實現一個delegate是很簡單的,通過以下3個步驟即可實現一個delegate
1.?聲明一個delegate對象,它應當與你想要傳遞的方法具有相同的參數和返回值類型。
2.?創建delegate對象,并將你想要傳遞的函數作為參數傳入。
3.?在要實現異步調用的地方,通過上一步創建的對象來調用方法。
下面是一個簡單的例子:

public class MyDelegateTest
{
??? // 步驟1,聲明delegate對象
??? public delegate void MyDelegate(string name);
??? // 這是我們欲傳遞的方法,它與MyDelegate具有相同的參數和返回值類型
??? public static void MyDelegateFunc(string name)
??? {
??????? Console.WriteLine("Hello, {0}", name);
??? }
??? public static voidMain ()
??? {
??????? // 步驟2,創建delegate對象
??????? MyDelegate md = new MyDelegate(MyDelegateTest.MyDelegateFunc);
??????? // 步驟3,調用delegate
??????? md("sam1111");
??? }
}

輸出結果是:Hello, sam1111
下面我們來看看事件是如何處理的:
事件(event)
C#中的事件處理實際上是一種具有特殊簽名的delegate,象下面這個樣子:
public delegate void MyEventHandler(object sender, MyEventArgs e);
其中的兩個參數,sender代表事件發送者,e是事件參數類。MyEventArgs類用來包含與事件相關的數據,所有的事件參數類都必須從System.EventArgs類派生。當然,如果你的事件不含特別的參數,那么可以直接用System.EventArgs類作為參數。
結合delegate的實現,我們可以將自定義事件的實現歸結為以下幾步:
1:定義delegate對象類型,它有兩個參數,第一個參數是事件發送者對象,第二個參數是事件參數類對象。
2:定義事件參數類,此類應當從System.EventArgs類派生。如果事件不帶參數,這一步可以省略。
3:定義事件處理方法,它應當與delegate對象具有相同的參數和返回值類型。
4:event關鍵字定義事件對象,它同時也是一個delegate對象。
5:+=操作符添加事件到事件隊列中(-=操作符能夠將事件從隊列中刪除)。
6:在需要觸發事件的地方用調用delegate的方式寫事件觸發方法。一般來說,此方法應為protected訪問限制,既不能以public方式調用,但可以被子類繼承。名字是可以是OnEventName
7:在適當的地方調用事件觸發方法觸發事件。
下面是一個例子,例子模仿容器和控件的模式,由控件觸發一個事件,在容器中捕捉并且進行處理。
事件的觸發者:

{
??? public delegate void SomeHandler(object sender, System.EventArgs e);
??? /**
??? public Control()
??? {
??????? //這里使用的delegate必須與事件中聲名的一致
??? }
??? public void RaiseSomeEvent()
??? {
??????? EventArgs e = new EventArgs();
??????? Console.Write("Please input 'a':");
??????? string s = Console.ReadLine();
??????? //在用戶輸入一個小a的情況下觸發事件,否則不觸發
??????? {
??????????? SomeEvent(this, e);
??????? }
??? }
??? //事件的觸發者自己對事件進行處理,這個方法的參數必須和代理中聲名的一致
??? {
??????? Console.WriteLine("hello");
??? }
}
??? private void ProcessSomeEvent(object sender, EventArgs e)
??????? if (s == "a")
??????? this.SomeEvent += new SomeHandler(this.ProcessSomeEvent);
??????? //this.SomeEvent += new System.EventHandler(this.Control_SomeEvent);
??? public event SomeHandler SomeEvent;
??? //public event System.EventHandler SomeEvent;
???? */
???? * 如果需要在事件的參數中使用自己定義的類型,也要自己定義delegate
???? * 可以采用系統提供的System.EventHandler, 這里為了說明情況使用了自己定義的delegate
public class Control
///</summary>
/// 事件的觸發者
///<summary>

事件的接收者:

{
??? private Control ctrl = new Control();
??? public Container()
??? {
??????? //這里使用的delegate必須與事件中聲名的一致
??????? ctrl.SomeEvent += new Control.SomeHandler(this.ResponseSomeEvent);
??????? ctrl.RaiseSomeEvent();
??? }
??? public static void Main()
??? {
??????? Container pane = new Container();
??????? //這個readline是暫停程序用的,否則畫面會一閃而過什么也看不見
??????? Console.ReadLine();
??? }
??? //這是事件的接受者對事件的響應
??? {
??????? Console.WriteLine("Some event occur!");
??? }
}
??? private void ResponseSomeEvent(object sender, EventArgs e)
??????? //ctrl.SomeEvent += new EventHandler(this.OnSomeEvent);
class Container
///</summary>
/// 事件的接收和處理者
///<summary>

程序運行的結果如下:
please input 'a':a
hello
Some event occur!
事件的應用
例如有下面的需求需要實現:程序主畫面中彈出一個子窗口。此時主畫面仍然可以接收用戶的操作(子窗口是非模態的)。子窗口上進行某些操作,根據操作的結果要在主畫面上顯示不同的數據。我發現一些程序員這樣實現這個功能:
主畫面彈出子窗口后,將自己的指針交給子畫面,然后在子畫面中使用這個指針,調用主畫面提供的方法,改變主畫面上的數據顯示。這樣雖然可以達到目的,但是各個模塊之間產生了很強的耦合。一般說來模塊之間的調用應該是單方向的:模塊A調用了模塊B,模塊B就不應該反向調用A,否則就破壞了程序的層次,加強了耦合程度,也使得功能的改變和追加變得很困難。
這時正確的做法應該是在子窗口的操作過程中發出各種事件,而由主窗口捕捉這些事件進行處理,各個模塊專心的做自己的事情,不需要過問其他模塊的事情。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/389265.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/389265.shtml
英文地址,請注明出處:http://en.pswp.cn/news/389265.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

BP神經網絡反向傳播手動推導

BP神經網絡過程&#xff1a; 基本思想 BP算法是一個迭代算法&#xff0c;它的基本思想如下&#xff1a; 將訓練集數據輸入到神經網絡的輸入層&#xff0c;經過隱藏層&#xff0c;最后達到輸出層并輸出結果&#xff0c;這就是前向傳播過程。由于神經網絡的輸出結果與實際結果…

使用python和pandas進行同類群組分析

背景故事 (Backstory) I stumbled upon an interesting task while doing a data exercise for a company. It was about cohort analysis based on user activity data, I got really interested so thought of writing this post.在為公司進行數據練習時&#xff0c;我偶然發…

3.Contructor(構造器)模式—精讀《JavaScript 設計模式》Addy Osmani著

同系列友情鏈接: 1.設計模式之初體驗—精讀《JavaScript 設計模式》Addy Osmani著 2.設計模式的分類—精讀《JavaScript 設計模式》Addy Osmani著 Construct&#xff08;構造器&#xff09;模式 在經典的面向對象編程語言中&#xff0c;Construtor是一種在內存已分配給該對象的…

BZOJ 3653: 談笑風生(離線, 長鏈剖分, 后綴和)

題意 給你一顆有 \(n\) 個點并且以 \(1\) 為根的樹。共有 \(q\) 次詢問&#xff0c;每次詢問兩個參數 \(p, k\) 。詢問有多少對點 \((p, a, b)\) 滿足 \(p,a,b\) 為三個不同的點&#xff0c;\(p, a\) 都為 \(b\) 的祖先&#xff0c;且 \(p\) 到 \(a\) 的距離不能超過 \(k\) 。 …

搜索引擎優化學習原理_如何使用數據科學原理來改善您的搜索引擎優化工作

搜索引擎優化學習原理Search Engine Optimisation (SEO) is the discipline of using knowledge gained around how search engines work to build websites and publish content that can be found on search engines by the right people at the right time.搜索引擎優化(SEO…

Siamese網絡(孿生神經網絡)詳解

SiameseFCSiamese網絡&#xff08;孿生神經網絡&#xff09;本文參考文章&#xff1a;Siamese背景Siamese網絡解決的問題要解決什么問題&#xff1f;用了什么方法解決&#xff1f;應用的場景&#xff1a;Siamese的創新Siamese的理論Siamese的損失函數——Contrastive Loss損失函…

Dubbo 源碼分析 - 服務引用

1. 簡介 在上一篇文章中&#xff0c;我詳細的分析了服務導出的原理。本篇文章我們趁熱打鐵&#xff0c;繼續分析服務引用的原理。在 Dubbo 中&#xff0c;我們可以通過兩種方式引用遠程服務。第一種是使用服務直聯的方式引用服務&#xff0c;第二種方式是基于注冊中心進行引用。…

期權價格的上限和下限

期權按照買方權利性質分為&#xff1a;看漲期權和看跌期權 1、首先&#xff0c;看漲期權的上限和下限 看漲期權價格上限為其標的資產價格。 看漲期權是給予買方一個在未來買入標的資產的權利&#xff0c;如果該權利的價格高于標的資產的價格&#xff0c;那么投資者不如直接購買…

一件登錄facebook_我從Facebook的R教學中學到的6件事

一件登錄facebookBetween 2018 to 2019, I worked at Facebook as a data scientist — during that time I was involved in developing and teaching a class for R beginners. This was a two-day course that was taught about once a month to a group of roughly 15–20 …

SiameseFC超詳解

SiameseFC前言論文來源參考文章論文原理解讀首先要知道什么是SOT&#xff1f;&#xff08;Siamese要做什么&#xff09;SiameseFC要解決什么問題&#xff1f;SiameseFC用了什么方法解決&#xff1f;SiameseFC網絡效果如何&#xff1f;SiameseFC基本框架結構SiameseFC網絡結構Si…

Python全棧工程師(字符串/序列)

ParisGabriel Python 入門基礎字符串&#xff1a;str用來記錄文本信息字符串的表示方式&#xff1a;在非注釋中凡是用引號括起來的部分都是字符串‘’ 單引號“” 雙引號 三單引""" """ 三雙引有內容代表非空字符串否則是空字符串 區別&#xf…

跨庫數據表的運算

跨庫數據表的運算&#xff0c;一直都是一個說難不算太難&#xff0c;說簡單卻又不是很簡單的、總之是一個麻煩的事。大量的、散布在不同數據庫中的數據表們&#xff0c;明明感覺要把它們合并起來&#xff0c;再來個小小的計算&#xff0c;似乎也就那么回事……但真要做起來&…

FCN全卷積網絡隨筆

參考&#xff1a;四、全卷積網絡FCN詳細講解&#xff08;超級詳細哦&#xff09; 這篇文章已經寫的很好了&#xff0c;這里說兩個我考慮的點。 第一個就是&#xff1a;FCN在縮小成heat map&#xff0c;為什么要通過上采樣還原回原圖大小&#xff1f; 我覺得這個的原因是因為&a…

熊貓在線壓縮圖_回歸圖與熊貓和脾氣暴躁

熊貓在線壓縮圖數據可視化 (Data Visualization) I like the plotting facilities that come with Pandas. Yes, there are many other plotting libraries such as Seaborn, Bokeh and Plotly but for most purposes, I am very happy with the simplicity of Pandas plotting…

敏捷數據科學pdf_敏捷數據科學數據科學可以并且應該是敏捷的

敏捷數據科學pdfTL;DR;TL; DR; I have encountered a lot of resistance in the data science community against agile methodology and specifically scrum framework; 在數據科學界&#xff0c;我遇到了許多反對敏捷方法論(特別是Scrum框架)的抵制。 I don’t see it this …

oracle的連接字符串

OracleConnection oCnn new OracleConnection("Data SourceORCL_SERVER;USERM70;PASSWORDmmm;");建立個角色 建立個表空間(角色與表空間同名的) 在方案里就可以建立表,然后就哦了 10g

SiameseRPN詳解

SiameseRPN論文來源論文背景一&#xff0c;簡介二&#xff0c;研究動機三、相關工作論文理論注意&#xff1a;網絡結構&#xff1a;1.Siamese Network2.RPN3.LOSS計算4.Tracking論文的優缺點分析一、Siamese-RPN的貢獻/優點&#xff1a;二、Siamese-RPN的缺點&#xff1a;代碼流…

數據可視化 信息可視化_可視化數據操作數據可視化與紀錄片的共同點

數據可視化 信息可視化Data visualization is a great way to celebrate our favorite pieces of art as well as reveal connections and ideas that were previously invisible. More importantly, it’s a fun way to connect things we love — visualizing data and kicki…

python 圖表_使用Streamlit-Python將動畫圖表添加到儀表板

python 圖表介紹 (Introduction) I have been thinking of trying out Streamlit for a while. So last weekend, I spent some time tinkering with it. If you have never heard of this tool before, it provides a very friendly way to create custom interactive Data we…