簡體   English   中英

如何重構此ForEach(..)代碼以使用Parallel.ForEach(..)?

[英]How can I refactor this ForEach(..) code to use Parallel.ForEach(..)?

我有一個對象列表,希望將其從一個來源復制到另一個來源。 有人建議我可以使用Parallel.ForEach 加快速度

我如何重構以下pseduo代碼以利用Parallel.ForEach(..)

var foos = GetFoos().ToList();
foreach(var foo in foos)
{
    CopyObjectFromOldBucketToNewBucket(foo, oldBucket, newBucket, 
        accessKeyId, secretAccessKey);
}

CopyObjectFromOldBucketToNewBucket使用Amazon REST API將項目從一個存儲桶移動到另一個存儲桶。

干杯:)

由於您的代碼除了對foos之外沒有任何依賴關系,您可以簡單地執行以下操作:

Parallel.ForEach(foos, ( foo => 
{
    CopyObjectFromOldBucketToNewBucket(foo, oldBucket, newBucket, 
                                       accessKeyId, secretAccessKey);
}));

但是請記住,在性能可能實際下降之后,I / O只能並行到一定程度。

實際上, Parallel並不是此處的最佳選擇。 ParallelParallel運行您的代碼,但仍將為每個對AWS的請求使用線程池線程。 最好使用資源來代替使用BeginCopyObject方法。 這不會耗盡等待響應的線程池線程,而只會在接收到響應並需要對其進行處理時才使用它。

這是有關如何使用Begin / End方法的簡化示例。 這些不是特定於AWS的,而是在整個.NET BCL中找到的一種模式。

public static CopyFoos() 
{
    var client = new AmazonS3Client(...);
    var foos = GetFoos().ToList();
    var asyncs = new List<IAsyncResult>();
    foreach(var foo in foos)
    {
        var request = new CopyObjectRequest { ... };  

        asyncs.Add(client.BeginCopyObject(request, EndCopy, client));
    }

    foreach(IAsyncResult ar in asyncs)
    {
        if (!ar.IsCompleted)
        {
            ar.AsyncWaitHandle.WaitOne();
        }
    }
}

private static EndCopy(IAsyncRequest ar) 
{    
    ((AmazonS3Client)ar.AsyncState).EndCopyObject(ar);
}

對於生產代碼,您可能希望跟蹤已發出的請求數量,並且一次只能發送有限數量的請求。 測試或AWS文檔可能會告訴您有多少並發請求是最佳的。

在這種情況下,當請求完成時,我們實際上不需要執行任何操作,因此您可能會想跳過EndCopy調用,但這會導致資源泄漏。 每當調用BeginXxx時,都必須調用相應的EndXxx方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM