2016-10-11 46 views
1

繼續提供圍繞Fire和Forget的許多問題提供的解決方案。我的情景是我想要運行被遺忘的事件以便觸發它們。火與遺忘(但不是完全)

我的解決方案是基於Simplest way to do a fire and forget method in c# 4.0

這裏是我的測試代碼。如預期的那樣,它永遠不會保證它們將被處理的順序。

static void Main(string[] args) 
    { 
     Test(5); 
     Console.WriteLine("5 sent"); 

     Test(2); 
     Console.WriteLine("2 sent"); 

     Test(1); 
     Console.WriteLine("1 sent"); 

     Test(4); 
     Console.WriteLine("4 sent"); 

     Console.WriteLine("all sent"); 
     Console.ReadLine(); 

    } 

    private static void Test(int messageNumber) 
    { 
     Action myMethod =() => { 
      Task.Delay(messageNumber * 1000); 
      Console.WriteLine(messageNumber); 
     }; 
     Blindly.Run(myMethod); 
    } 

和我的輸出

5 sent 
2 sent 
1 sent 
4 sent 
all sent 
2 
1 
5 
4 

試想一下,你正在使用消防和忘記了記錄。所以你不想阻止調用代碼,但想要寫入所有記錄的數據以便它們發生。

+1

爲什麼不排隊你的行爲和你想要的順序調用它們? – Shocked

+0

你確實意識到Task.Delay(messageNumber * 1000);'在這種情況下沒用,因爲它沒有等待?在下一行'Console.WriteLine(messageNumber);'之前不會有延遲 –

回答

1

我會用ActionBlock的TPL數據流的(對於一個見http://blog.stephencleary.com/2012/09/introduction-to-dataflow-part-2.html簡介)

這是一個NuGet包,看看它是否符合你的框架版本要求。

static void Main(string[] args) 
{ 
    var a = new ActionBlock<int>(async (messageNumber) => 
    { 
     await Task.Delay(messageNumber * 1000); 
     Console.WriteLine(messageNumber); 
    }); 

    a.Post(5); 
    Console.WriteLine("5 sent"); 

    a.Post(2); 
    Console.WriteLine("2 sent"); 

    a.Post(1); 
    Console.WriteLine("1 sent"); 

    a.Post(4); 
    Console.WriteLine("4 sent"); 

    Console.WriteLine("all sent"); 
    Console.ReadLine(); 
} 

它將在已發佈到ActionBlock的順序發射後不管的方式進行處理。

輸出:

5 sent 
2 sent 
1 sent 
4 sent 
all sent 
5 
2 
1 
4 
0

我會做到以下幾點:

  • 保持時間戳的所有記錄的事件
  • 不寫事件立即登錄(因爲你異步運行它,你希望已經不那麼擔心了);如果您有排隊的日誌消息,排序並記錄所有年齡大於Y毫秒的日誌(X和Y將取決於您的要求),請每隔X毫秒保留一個記錄消息的隊列(集合,不一定是FIFO)
  • /設置)
  • 嘗試刷新日誌每當應用程序退出(確保你正在做它,即使它是一個例外)