4

我在閱讀C# 5.0 in nutshell,在閱讀作者的觀點後,我對我應該採用什麼感到困惑。我的要求是說,我有一個非常長的運行(計算繁重)任務,例如說,計算數百萬文件的SHA1(或其他)散列,或者真的任何其他事情是計算量很大並且可能需要一些時間,我應該如何開發它(如果有問題,請使用VS 2012,C#5.0),so that I can also report progress to the userPLINQ vs任務vs異步vs生產者/消費者隊列?要使用什麼?

以下情形(S)浮現在腦海中......

  1. 創建Task(與LongRunning選項計算哈希值,並通過實施IProgess<T>Progess<T>報告進度,用戶要麼讓任務捕獲SynchronizationContext上下文併發布到UI。

  2. 創建一個Async方法,如

    async CalculateHashesAsync() 
    { 
        // await here for tasks the calculate the hash 
        await Task.Rung(() => CalculateHash(); 
        // how do I report progress??? 
    } 
    
  3. 使用TPL(或PLINQ)作爲

    void CalcuateHashes() 
    { 
        Parallel.For(0, allFiles.Count, file => calcHash(file)  
        // how do I report progress here? 
    } 
    
  4. 使用生產者/消費者隊列。
    真的不知道如何?

書中的作者說...

運行在一個線程池一個長期運行的任務不會造成 麻煩。這是當你並行運行多個長時間運行的任務時 (特別是那些阻止)性能會受到影響的任務。在這種情況下 ,通常有更好的解決方案比 TaskCreationOptions.LongRunnging

  • 如果任務IO約束,TaskCompletionSource和異步功能,讓你 實現併發性的回調,而不是線程。
  • 如果任務是計算綁定的,則可以使用生產者/消費者隊列來限制這些任務的併發性,從而避免其他線程和進程的不足。

關於Producer/Consumer作者說...

生產者/消費者隊列是一個有用的結構,無論是在並行編程 和一般的併發場景,因爲它給你精確 控制一次執行多少個工作線程,這不僅限制CPU消耗,還有其他資源。

那麼,我不應該使用任務,這意味着第一個選項出來了嗎?第二個是最好的選擇?還有其他選擇嗎?如果我是按照筆者的建議,並實現了一個生產者/消費者,我該怎麼做(我甚至不有一個如何與生產者/消費者在我的情況下開始的想法,如果那是最好的接近!)

我想知道是否有人曾經碰到過這樣的情況,他們會怎麼實現?如果沒有,什麼是性能最有效的和/或易於開發/維護(我知道這個詞performance是主觀的,但我們只是認爲它的工作原理,並且效果很好的很一般情況下!)

+0

你看着TPL數據流?它旨在使生產者/消費者代碼更易於編寫。 –

+0

另外,從我現在看到的,沒有* *消費者這裏邊,只有*出品商*(計算哈希值),在那裏做這些哈希去以後呢? –

+0

@PatrykĆwiek:保存到一個文件。那麼,你認爲我應該選擇2? – Razort4x

回答

6

真正長時間運行(計算量大)的任務,例如說,計算SHA1(或其他)數百萬文件的散列

該示例明顯具有繁重的CPU(哈希)和I/O(文件)組件。也許這是一個非代表性的例子,但以我的經驗來看,即使是安全的哈希也比從磁盤讀取數據快得多。

如果你只是有CPU限制的工作,最好的解決方法是,Parallel或PLINQ。如果你只有I/O綁定的工作,最好的解決方案是使用async。如果你有一個更現實和更復雜的場景(CPU和I/O都可以工作),那麼你應該用生產者/消費者隊列來連接你的CPU和I/O部分,使用更完整的解決方案,如TPL Dataflow 。

TPL數據流在並行(MaxDegreeOfParallelism)和async之間運行良好,並且在每個塊之間都有內置的生產者/消費者隊列。

混合大量I/O和CPU使用率時要記住的一件事情是,不同的情況會導致大量不同的性能特徵。爲了安全起見,您需要限制隊列中的數據,以免導致內存使用問題。 TPL Dataflow內置支持通過BoundedCapacity進行節流。