2010-03-17 59 views
41

我試圖在c#中實現生產者/消費者模式。我有一個消費者線程監視共享隊列和一個將項目放到共享隊列中的生產者線程。生產者線程訂閱接收數據......也就是說,它有一個事件處理程序,並且只是坐在旁邊等待一個OnData事件觸發(數據從第三方api發送)。當它獲取數據時,它將它放在隊列中,以便消費者可以處理它。在.NET中,事件處理的線程是什麼?

當OnData事件在生產者中觸發時,我期望它被我的生產者線程處理。但這似乎並不是正在發生的事情。 OnData事件就好像它正在一個新的線程上處理一樣!這是.net總是如何工作...事件是在自己的線程處理?我可以控制什麼線程會在事件發生時處理事件嗎?如果幾乎同時發生數百個事件會怎麼樣?每個事件都有自己的線程?

+0

它可能有助於發佈一些代碼和/或您正在使用的類。 – 2010-03-17 02:55:53

+0

你是說C#事件關鍵字意義上的事件,還是EventWaitHandle意義上的事件?我認爲你應該發佈一些代碼... – 2010-03-17 03:03:30

+0

@codeka:這聽起來像'事件',給他的職位。 – 2010-03-17 03:06:16

回答

22

除非你自己進行編組,否則一個事件將在任何線程調用它時執行;事件調用方式沒有什麼特別之處,而且您的生產者線程沒有事件處理程序,您的生產者線程只是簡單地說:「嘿,當您觸發此事件時,請調用此函數」。沒有任何東西會導致事件執行發生在附加線程上,也不會在其自己的線程上發生(除非您使用BeginInvoke而不是正常調用事件的委託,但這隻會在ThreadPool上執行它)。

74

重新閱讀這個問題後,我想我現在明白了這個問題。你基本上有這樣的東西:

class Producer 
{ 
    public Producer(ExternalSource src) 
    { 
     src.OnData += externalSource_OnData; 
    } 

    private void externalSource_OnData(object sender, ExternalSourceDataEventArgs e) 
    { 
     // put e.Data onto the queue 
    } 
} 

然後你有一個消費者線程,從那個隊列拉東西。問題在於OnData事件是由你的ExternalSource對象觸發的 - 在任何正在運行的線程上。

C#event s基本上只是一個易於使用的委託集合,「觸發」事件只會導致運行時循環遍歷所有委託並逐個觸發它們。

因此,您的OnData事件處理程序正在運行ExternalSource的任何線程上調用。

+1

感謝Codeka,你已經準確無誤了。我將檢查externalSource事件發生的線程。我很感激幫助。 – Ben 2010-03-17 14:30:55

+13

@Ben - 您應該將此標記爲已接受的答案。這將幫助其他人更容易地看到答案。 – 2010-11-15 14:54:07

+1

當使用Invoke觸發事件時,事情是不同的,並且BeginInvoke..BeginInvoke在與threadpool不同的線程中調用事件訂閱者(在後臺線程中) – 2017-05-17 23:35:26

7

Invoke提高事件與調用方法相同 - 它會在您提出的同一個線程中執行。

BeginInvoke提高事件使用ThreadPool。這裏有一些minor details

-3

你必須使用autoresetevent處理這個問題.....在autoresetevent當生產者生產它設置信號然後消費者重置其信號並消耗..消耗後消耗設置信號,然後只有生產者生產。 ..

AutoResetEvent pro = new AutoResetEvent(false); 
AutoResetEvent con = new AutoResetEvent(true); 

public void produser() 
{ 

    while(true) 
    { 
     con.WaitOne(); 

     pro.Set(); 
    } 
} 

public void consumer() 
{ 
    while (true) 
    { 
    pro.WaitOne(); 
     .................**** 

    con.Set(); 
    } 
} 

private void button1_Click(object sender, EventArgs e) 
{ 
    Thread th1 = new Thread(produser); 
    th1.Start(); 
    Thread th2 = new Thread(consumer); 
    th2.Start(); 
} 
相關問題