在我的代码中,我使用 SemaphoreSlim
,在执行整个 for
循环后,我收到来自 App.g.cs
的异常 信号量已被释放
,如果仅通过using
语句释放信号量,我无法找出原因。这是使用的整个方法的代码:
public async Task TestHistoricalResultsAsync()
{
//init values and controls
CommandStartedControlsSetup("TestResultsCommand");
List<Task> tasks = new List<Task>();
int degreeOfParallelism = 10;
int loopCounter = 0;
ProgressBarTick("Testing on historic data", loopCounter, Races.Count, 0);
using (var throttler = new SemaphoreSlim(degreeOfParallelism))
{
//for all races in the file
for (int i = 0; i < Races.Count; i++)
{
int j = i;
if (TaskCancellation == true)
{
break;
}
await throttler.WaitAsync(TokenSource.Token);
tasks.Add(Task.Run(() => //async
{
try
{
CancellationToken.ThrowIfCancellationRequested();
//if the race is from 2018
if (Races[j].RaceDate.Year == 2018)
{
Category = Races[j].RaceCategory;
Distance = Races[j].RaceDistance.ToString();
//for all horses in the race
for (int h = 0; h < Races[j].HorseList.Count; h++)
{
if (TaskCancellation == true)
{
break;
}
CancellationToken.ThrowIfCancellationRequested();
HorseDataWrapper horse = new HorseDataWrapper();
horse = ParseHorseData(Races[j].HorseList[h], Races[j].RaceDate);
Races[j].HorseList[h] = horse; //get all indexes
}
}
}
catch (Exception e)
{
//
}
finally
{
loopCounter++;
ProgressBarTick("Testing on historic data", loopCounter, Races.Count, 0);
throttler.Release();
}
}));
}
}
try
{
//ThreadPool.SetMinThreads(100, 100);
await Task.WhenAll(tasks);
}
catch (OperationCanceledException)
{
//
}
finally
{
await _dataServices.SaveRaceTestResultsAsync(Races.ToList()); //save the analysis to the file
AllControlsEnabled = true;
CommandCompletedControlsSetup();
VisibilityCancellingMsg = Visibility.Collapsed;
}
}
最佳答案
根据评论讨论,问题是您的信号量超出了范围。您有两个选择:
a) 等待 block 内所有任务的执行
using (var throttler = new SemaphoreSlim(degreeOfParallelism))
{
// setup the tasks
try
{
await Task.WhenAll(tasks);
}
// ...
}
b) 所有任务执行完成后手动处置
var throttler = new SemaphoreSlim(degreeOfParallelism)
{
// setup the tasks. You can still use a scope block (brackets) here if you want.
}
try
{
await Task.WhenAll(tasks);
// ...
}
finally
{
throttler?.Dispose()
}
第二个选项很可能更合适,但这取决于代码的最终布局。
关于c# - 为什么我的代码抛出 `The semaphore has been disposed` 异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56640694/