锁定异步上下文的替代方案?

时间:2018-02-27 18:00:42

标签: c# async-await locking

上下文:原始聊天机器人。

我有一个简单的代码:

private static bool busy;
private async void OnTimedEvent(object sender, ElapsedEventArgs e)
{
    if (!busy)
    {
        busy = true;
        //some logic
        await SomeAsyncCommand();
        busy = false;
    }
    else
    {
        await Reply("Stuff's busy yo"); // falling thru, no need to process every request
    }
}

到目前为止它工作正常,我还没有遇到bool的任何“非原子精度问题”。当我开始在async / await上下文中执行更复杂的操作时会出现问题,例如:

public async Task AddEntry(string url, DateTime time, User user)
{
    UpdateUser(user);
    // We cant fall thru here, all sent requests MUST be processed so we wait
    while (busy)
    {
        await Task.Delay(100); // checking every 100ms if we can enter
    }
    busy = true;
    // working with NON-CONCURRENT collection
    // can await as well
    busy = false;
}

我的理解是 - 当这些线程堆积起来等待“布尔锁定”被释放时,可能会出现这样一种情况,即其中两个将同时进入并杀死。

我知道我不能在await / async上下文中使用lock(我也在这里读过CLR锁在async / await env中的一个坏习惯吗?)而且我知道bool也不是很好的选择。

这些情况通常如何处理?

2 个答案:

答案 0 :(得分:0)

您最好查看SemaphoreSlimInterlocked.CompareExchange
例如

private static SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(0, 1);
private async void OnTimedEvent(object sender, ElapsedEventArgs e)
{
    bool busy = await _semaphoreSlim.WaitAsync(0); //instantly return with false if busy
    if(!busy)
    {
        try
        {
            //some logic
            await SomeAsyncCommand();
        }
        finally
        {
            _semaphoreSlim.Release();
        }
    }
    else
    {
        await Reply("Stuff's busy yo"); // falling thru, no need to process every request
    }
}

private static SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(0, 1);
public static async Task AddEntry(string url, DateTime time, User user)
{
    UpdateUser(user);
    await _semaphoreSlim.WaitAsync();
    try
    {
        // do job
    }
    finally
    {
        _semaphoreSlim.Release();
    }
}

答案 1 :(得分:-1)

没有一堆线程堆积起来。只要您等待异步调用,该方法将按顺序运行,只有在此方案中运行Task.Delay时,它才会产生可在其他地方运行的其他东西。所以根本不需要使用锁。