2011-05-04 82 views
0

我正在研究一個類庫,它根據Web配置文件中定義的策略在多種數據源(文件,xml,數據庫)中記錄Web應用程序的審計詳細信息。異步方法調用的排序

我的審覈日誌方法有一個類似於此的簽名: public static void LogInfo(User user,Module module,List lst);

Web應用程序使用此方法記錄重要的細節,如警告,錯誤甚至異常詳細信息。

由於在單個工作流程中,有超過700多次對這些方法的調用,所以我認爲它們是異步的。我從線程池用簡單的方法類稱爲QueueUserWorkItem

ThreadPool.QueueUserWorkItem(o => LogInfo(User user, Module module, List<Object> lst)); 

但是這並不能保證在工作項排隊到它的順序。儘管我的所有信息都被記錄下來,但整個訂單都搞亂了。在我的文本文件中,我的日誌沒有按照它們被調用的順序。

有沒有一種方法可以控制使用QueueUserWorkItem調用的線程的順序?

回答

2

我不認爲你可以指定使用QueueUserWorkItem時的順序。

要並行運行日誌記錄(在某些後臺線程上),可以使用ConcurrentQueue<T>。這是一個線程安全的集合,可以從多個線程訪問。您可以創建一個工作項目(或一個線程),該工作項目從集合中讀取元素並將它們寫入文件。您的主應用程序會將項目添加到集合中。從單個線程向集合中添加項目的事實應該保證以正確的順序讀取它們。

爲了簡單起見,你可以存儲在隊列Action值:

ConcurrentQueue<Action> logOperations = new ConcurrentQueue<Action>(); 

// To add logging operation from main thread: 
logOperations.Add(() => LogInfo(user, module, lst)); 

後臺任務可以只取Action■從隊列中並運行它們:

// Start this when you create the `logOperations` collection 
ThreadPool.QueueUserWorkItem(o => { 
    Action op; 
    // Repeatedly take log operations & run them 
    while (logOperations.TryDequeue(out op)) op(); 
}); 

如果您需要要停止後臺處理器(將數據寫入日誌),您可以創建一個CancellationTokenSource,並在令牌被取消時(主線程)結束while循環。此七使用IsCancellationRequested財產(see MSDN)解決,這將是把你的數據在一個隊列,然後有一個單一的任務從隊列採摘,爲了寫他們的

+0

**編輯**我最初建議使用'BlockingCollection',但在這種情況下使用'ConcurrentQueue'就夠了。(其實,我在看到Brizio的答案之前甚至意識到這一點:-)) – 2011-05-04 21:58:25

+0

我將從頁面的生命週期事件多次調用審計方法。實際上,它也可以從單個方法多次調用。 Can ConcurrentQueue 是否照顧這個? – 2011-05-04 22:04:28

+0

@Kunal:是的,您可以添加多個動作(通過重複調用「添加」)。 – 2011-05-04 22:06:31

0

一種方式進行檢查。如果您使用.net 4.0您可以使用ConcurrentQueue,這是線程安全的,否則具有適當鎖定的簡單隊列也可以工作。

消耗隊列的線程可以定期檢查隊列中的任何元素,並且可以記錄每個元素。這樣,冗長的操作(日誌記錄)可以在它自己的線程中,而在主線程中,您只需添加。