在我的代码中,我正在使用SemaphoreSlim
,在执行了整个for
循环之后,我收到了App.g.cs
异常The semaphore has been disposed
的消息,我无法找出原因,如果它仅由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;
}
}
答案 0 :(得分:2)
根据评论讨论,问题在于您的信号量超出了范围。您有两种选择:
a)等待块中所有任务的执行
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()
}
第二个选项很可能更合适,但这取决于代码的最终布局。