Nig*_*sey 1 .net c# task-parallel-library
我有以下控制台应用程序,它将从超过 7 天的存储帐户容器中删除 blob。
我试图通过调用 WriteNumberFilesProcessed() 在控制台屏幕上创建一个反馈循环,一旦 blob 被删除,它就会增加成员变量 _counter,然后写入控制台。
问题是当最后一个任务在 TPL foreach 循环中完成而不是 _counter 成员变量从 29999 到 30000 时,它将是更远的东西,即 29995。
我不确定我需要做什么来确保 TPL foreach 循环获得最新的成员变量?
class Program
{
static int _counter = 0;
static int _numBlobsToDelete = 30000;
static int _blobCount = 0;
static void Main(string[] args)
{
GetOldBlobs();
Console.ReadLine();
}
static async void GetOldBlobs()
{
try
{
Stopwatch stopWatch = new Stopwatch();
CloudStorageAccount acc = CloudStorageAccount.Parse("");
var client = acc.CreateCloudBlobClient();
var container = client.GetContainerReference("");
var rollingTotal = 0;
while (true)
{
stopWatch.Restart();
Console.WriteLine($"{DateTime.Now}:\tGetting blobs older than a week in a batch of {_numBlobsToDelete}...");
var blobs = container.ListBlobs("", true).OfType<CloudBlockBlob>().Where(b => (DateTime.UtcNow.AddDays(-7) > b.Properties.LastModified.Value.DateTime)).Take(_numBlobsToDelete).ToList();
_blobCount = blobs.Count();
_counter = 0;
Console.WriteLine($"{DateTime.Now}:\tTime taken to get {_numBlobsToDelete} blobs - {stopWatch.Elapsed}");
Console.WriteLine($"{DateTime.Now}:\tDeleting {_blobCount} blobs...");
try
{
Parallel.ForEach(blobs, blob => DeleteBlob(blob));
}
catch (Exception ex)
{
Console.WriteLine($"{DateTime.Now}:\t{ex.Message}");
}
rollingTotal += _blobCount;
Console.WriteLine($"\n{DateTime.Now}:\tTime taken to delete blobs - {stopWatch.Elapsed}");
Console.WriteLine($"{DateTime.Now}:\t{rollingTotal} blobs deleted since startup");
Console.WriteLine($"{DateTime.Now}:\tSleeping for 5 seconds...\n");
await Task.Delay(5000);
}
}
catch (Exception ex)
{
Console.WriteLine($"{DateTime.Now}:\t{ex.Message}");
}
}
public static void DeleteBlob(CloudBlockBlob blob)
{
try
{
blob.Delete();
WriteNumberFilesProcessed();
}
catch (Exception ex)
{
Console.WriteLine($"{DateTime.Now}:\t{ex.Message}\n");
}
}
public static void WriteNumberFilesProcessed()
{
_counter++;
Console.Write($"\r{_counter} of {_blobCount}");
}
}
Run Code Online (Sandbox Code Playgroud)
您的问题是多个线程同时调用_counter++。这会导致竞争条件。
要修复它,最简单的方法是使用如下Interlocked方法之一:
Interlocked.Increment(ref _counter);
Run Code Online (Sandbox Code Playgroud)
不使用锁定,可能发生的事情是(给定线程 A 和线程 B):
假设 _counter 的值为 1:
Thread A: reads value of _counter -> 1
Thread B: reads value of _counter -> 1
Thread A: adds 1 to the value it read -> 2
Thread B: adds 1 to the value it read -> 2
Thread A: writes value back to _counter -> 2
Thread B: writes value back to _counter -> 2
Run Code Online (Sandbox Code Playgroud)
现在_counter有了价值2而不是它应该具有的价值,3。
| 归档时间: |
|
| 查看次数: |
40 次 |
| 最近记录: |