为什么我的代码抛出“信号量已被处置”异常?

时间:2019-06-18 01:31:57

标签: c# wpf task

在我的代码中,我正在使用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;
    }
}

1 个答案:

答案 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()
}

第二个选项很可能更合适,但这取决于代码的最终布局。