[英]Parallel.ForEach Loop with Retry Logic in C#
我正在使用Parallel.ForEach
將 C# 中的多個文件從谷歌存儲桶下載到文件夾位置。 我正在使用重試邏輯,因此它可以重試下載文件,以防下載過程中文件下載失敗。 如何為Parallel.ForEach
循環中的每個文件或每個線程應用重試邏輯。
Parallel.ForEach(listFiles, objectName =>
{
retryCount = 0;
countOfFiles++;
downloadSuccess = false;
bucketFileName = Path.GetFileName(objectName.Name);
guidFolderPath = tempFolderLocation + "\\" + bucketFileName;
while (retryCount < retryCountInput && downloadSuccess == false)
{
try
{
FileStream fs = new FileStream(guidFolderPath, FileMode.Create, FileAccess.Write, FileShare.Write);
using (fs)
{
storage.DownloadObjectAsync(bucketName, objectName.Name, fs, option, cancellationToken, progress).Wait();
}
}
catch (Exception ex)
{
Console.WriteLine("Exception occured while downloading file: " + ex.ToString());
Thread.Sleep(RetryInterval(retryCount, minBackoffTimeSpan, maxBackoffTimeSpan, deltaBackoffTimeSpan));
retryCount++;
}
}
}
我會將其更改為任務並使用異步。 這樣你的 Thread.Sleep 不會阻塞線程池線程。 Parallel.ForEach 用於 CPU 密集型工作。
類似於:(如果沒有您的代碼的 rest,我將無法編譯/測試它)
int retryCountInput = 5;
var tasks = new List<Task>();
foreach (var file in listFiles)
{
var task = Task.Run(async () =>
{
// make it local
int retryCount = 0;
string bucketFileName = Path.GetFileName(objectName.Name);
string guidFolderPath = tempFolderLocation + "\\" + bucketFileName;
while (retryCount < retryCountInput)
{
try
{
using (var fs = new FileStream(guidFolderPath, FileMode.Create, FileAccess.Write, FileShare.Write))
// Use await here, instead of `Wait()` so this threadpool thread
// can be used for other tasks.
await storage.DownloadObjectAsync(bucketName, objectName.Name, fs, option, cancellationToken, progress);
break;
}
catch (Exception ex)
{
Console.WriteLine("Exception occured while downloading file: " + ex.ToString());
// Use Task.Delay here, so this thread is 'released'
await Task.Delay(RetryInterval(retryCount, minBackoffTimeSpan, maxBackoffTimeSpan, deltaBackoffTimeSpan));
retryCount++;
}
}
});
tasks.Add(task);
}
await Task.WhenAll(tasks);
我已經修改了我的代碼並刪除了Parallel.ForEach
,而是使用foreach
循環來遍歷文件。 但是現在,我無法在下載路徑中找到所有文件,盡管日志顯示所有文件都已下載。 下載路徑中下載文件的數量發生了變化,這種行為似乎是隨機的。 我可以使用Task.Run
進行 I/O 操作嗎?
var tasks = new List<Task>();
foreach (var objectName in listFiles)
{
var task = Task.Run(() =>
{
downloadSuccess = false;
bucketFileName = Path.GetFileName(objectName.Name);
guidFolderPath = tempFolderLocation + "\\" + bucketFileName;
var maxRetryAttempts = 3;
var pauseBetweenFailures = TimeSpan.FromSeconds(2);
RetryHelper.RetryOnException(maxRetryAttempts, pauseBetweenFailures, async () =>
{
FileStream fs = new FileStream(guidFolderPath, FileMode.Create,
FileAccess.Write, FileShare.Write);
using (fs)
{
var progress = new Progress<IDownloadProgress>(
p =>
{
DownloadProgress(p, retryCount, objectName.Name);
});
await client.DownloadObjectAsync(bucketName, objectName.Name,
fs, option, cancellationToken.Token, progress);
}
});
});
tasks.Add(task);
}
await Task.WhenAll(tasks);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.