繁体   English   中英

等待所有线程释放信号量?

[英]Wait for all threads to release semaphore?

如何关闭并等待信号量完全释放?

private SemaphoreSlim _processSemaphore = new SemaphoreSlim(10);

public async Task<Modification> Process(IList<Command> commands)
{
  Assert.IsFalse(_shuttingDown, "Server is in shutdown phase");
  await _processSemaphore.WaitAsync();

  try
  {
    // threads that have reached this far must be allowed to complete
    return _database.Process(commands);
  }
  finally
  {
    _processSemaphore.Release();
  }
}

public async Task StopAsync()
{
  _shuttingDown = true;

  // how wait for threads to complete without cancelling?
  await ?
}
    private SemaphoreSlim _processSemaphore = new SemaphoreSlim(10);
    private int _concurrency;
    private TaskCompletionSource<int> _source;
    private ManualResetEvent _awaitor;

    public void Start()
    {
        //solution 1
        _concurrency = 0;
        _source = new TaskCompletionSource<int>();
        _shuttingDown = false;

        //solution 2
        _awaitor = new ManualResetEvent(false);

        //your code
    }
    public async Task<Modification> Process(IList<Command> commands)
    {
        Interlocked.Increment(ref _concurrency);
        Assert.IsFalse(_shuttingDown, "Server is in shutdown phase");
        await _processSemaphore.WaitAsync();

        try
        {
            // threads that have reached this far must be allowed to complete
            return _database.Process(commands);
        }
        finally
        {
            _processSemaphore.Release();


            //check and release
            int concurrency = Interlocked.Decrement(ref _concurrency);
            if (_shuttingDown && concurrency == 0)
            {
                //solution 1
                _source.TrySetResult(0);

                //solution 2
                _awaitor.Set();
            }
        }

    }

    public async Task StopAsync()
    {
        _shuttingDown = true;

        // how wait for threads to complete without cancelling?
        if (Interlocked.CompareExchange(ref _concurrency, 0, 0) != 0)
        {
            await _source.Task;//solution 1

            _awaitor.WaitOne();//solution 2
        }
    }

可能不是你所需要的,但我有一个类似的情况,我用CountdownEvent 类解决了它

private  CountdownEvent _countdownEvent = new CountdownEvent(1);

process_method() {
        //if the count is zero means that we already called finalize
        if (_countdownEvent.IsSet)
            return;

        try
        {
            //this can throw and exception if we try to add when the countdown has already reached 0.
            //this exception happens when one process_method B has passed the _counddownEvent.IsSet check and context switched to
            //to another process_method A that was the last one (after finalize waits for 0) and sets the countdown to 0. Which
            //triggers finalization and should not allow new process_method, so process_methodB not continuing is good (finalization is
            //in progress).
             _countdownEvent.AddCount(1);

        } catch
        {
            return;
        }
        

        try
        {
            //your process
        }
        finally
        {
            _countdownEvent.Signal();
        }
}

然后当你准备好等待计数为零时:

finalize() {
   _countdownEvent.Signal();
   _countdownEvent.Wait(_finalizationSafetyTimeout, cancellationToken)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM