2015-06-03 70 views
1

我可能過分複雜化了,但是我一直被困住了,而且我發現自己編寫了一個真正愚蠢的解決方案來解決這個問題。C#控制被解僱的次數

這裏是場景。我有在未來數流。1,2,3,4,5,6,6,6,5,6等....

private void NotifyAlert(int p) 
    { 
     EventHandler<DataEventArgs> handler = Value; 
     if (handler != null) 
     { 
      handler(this, new DataEventArgs(p)); 
     } 

    } 



if(x > 4) 
{ 
    NotifyAlert(x); 
    return; 
} 

所以發生了什麼是事件觸發該值大於4,然後5,然後6 ...等,並在我的事件處理程序

private static void ValueAlertHandler(object sender, DataEventArgs e) 
    { 
     lock (locker) 
     { 
      if (Convert.ToInt32(e.Message) > 4) 
      { 

       SendUpdate(e.message); 
      } 
     } 
    } 

我要的是,它只能調用SendUpdate()一次當值被擊中,但它被稱爲爲之後的每個值。 我知道我錯過了什麼,只是不知道是什麼。先謝謝你們。

編輯:澄清。我想要的是在數字超過4並且調用SendUpdate()方法一次時引發的事件。然後,如果數字低於4並再次回到4以上,則調用SendUpdate()一次。這個過程將重複。

+0

你是說你一旦調用了SendUpdate,你就不想再次調用它了嗎? –

+0

@BillGregg對不起,我希望它調用一次值,而不是其他值。例如(x> 4將事件稱爲方法),並且如果數字流不到4,則再次返回提升事件並僅調用該方法一次。 – Valmorgal

+0

@Valmorgal:您可能想編輯原始帖子以反映您對需求的更改。 – sstan

回答

0

爲了得到這個工作,首先,你將需要刪除的條件,「如果(X> 4)」,圍繞呼叫「NotifyAlert(X)」。你需要被調用的所有值,而不只是那些大於4

因此,而不是方法...

if(x > 4) 
{ 
    NotifyAlert(x); 
    return; 
} 

......根本就......

NotifyAlert(x); 

這是重要的第一步。

然後修改,像這樣的事件處理程序的代碼:

private static bool isOver4 = false;  

private static void ValueAlertHandler(object sender, DataEventArgs e) 
{ 
    lock (locker) 
    { 
     int x = Convert.ToInt32(e.Message); 
     if (x > 4) 
     { 
      if (!isOver4) 
      { 
       SendUpdate(e.message); 
       isOver4 = true; 
      } 
     } 
     else 
     { 
      isOver4 = false; 
     } 
    } 
} 

(*)注1:您還可以選擇移動整個邏輯出了事件處理程序,並把它調用NotifyAlert各地(x),正如其他人所建議的那樣。但是,由於您正在事件處理程序中進行一些併發控制(鎖定'locker'),因此您可能希望對值進行跟蹤以串行方式完成。至少,這似乎是你的意圖。在這種情況下,邏輯需要發生在事件處理程序內部。

(*)注2:我注意到你的帖子有點矛盾。您的代碼表明事件在值大於4時開始觸發。然而,從您的書面解釋中,我們被認爲事件在值爲等於或大於4時觸發。請務必調整比較你的要求是什麼。

+0

我會嘗試使用它,是的,你是正確的發生在SendUpdate()方法中的一些併發的東西。我會給這個鏡頭。此外,我更新的帖子顯示大於4. – Valmorgal

+0

如果你發現這個答案有用,一個接受的答案總是讚賞:) – sstan

3
private static bool _alertedAlready = false; 

private static void ValueAlertHandler(object sender, DataEventArgs e) 
{ 
    lock (locker) 
    { 
     if (Convert.ToInt32(e.Message) > 4) 
     { 
      if (!_alertedAlready) 
      { 
       SendUpdate(e.message); 
       _alertedAlready = true; 
      } 
     } 
    } 
} 

你可以重寫這個在許多方面看起來更好,但這個想法依然存在。您需要指出這是否是第一次警報。

+0

你可以將ifs合併到if(Convert.ToInt32(e.Message)> 4 &&!_alertedAlready)' – StuperUser

+2

@StuperUser True。我個人甚至更喜歡'if(_alertedAlready)return;'在鎖之前。正如我所說,你可以在很多方面讓這看起來更好。 – SimpleVar

0

從它的聲音中,您只希望事件在達到閾值時觸發,而不是讓事件處理程序通過調用SendUpdate來決定是否處理該事件。

我會設置它,以便NotifyAlert只在實際需要時才被調用,而不是讓事件處理程序知道更多的需要。例如,事件處理程序是否也必須知道閾值是4?目前,如果您需要更改閾值,則必須在多個位置執行此操作。舉例來說,你可以做這樣的事情:

Action<int> SendNotification = (p) => NotifyAlert(p); 
Action<int> IgnoreValue = (p) -> {}; 
Action<int> Notify = SendNotification; 

... 

if(x > 4) 
{ 
    Notify(x); 
    Notify = IgnoreValue; 
    return; 
} 
else 
{ 
    Notify = SendNotification; 
    return; 
} 

這比簡單地使用一個布爾值來決定是否要觸發事件更詳細的,但它也允許有靈活性 - 你可能要在內部做一些事情任何時候該值都高於閾值,但不一定會觸發事件。

加入國旗: private bool alreadyAboveThreshold = false;

... 

if(x > 4 && !alreadyAboveThreshold) 
{ 
    NotifyAlert(x); 
    alreadyAboveThreshold = true; 
    return; 
} 
else 
{ 
    alreadyAboveThreshold = false; 
    return; 
} 
+0

是的,我希望事件發生一次。我會怎麼做呢? :) – Valmorgal

+0

我在我的答案中放置的代碼會起作用,因爲它只會在第一次調用'NotifyAlert'時超出閾值。然後它將'Notify'動作設置爲一個什麼都不做的函數。所以下一次'x'超過閾值時,對'Notify(x)'的調用將調用空函數。如果'x'低於閾值,那麼'Notify'會重新設置爲'NotifyAlert',導致下一次'x'超過閾值時再次觸發事件。 – Craig

+0

我使用標記添加了示例代碼,而不是將單獨的「Action 」實例添加到我的答案中。 – Craig