SemaphoreSlim和async/await

Sin*_*atr 0 c# synchronization semaphore

这有效:

int _counter;
readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);

async void Button_Click(object sender, RoutedEventArgs e)
{
    if (_semaphore.Wait(0))
    {
        Title = $"{ ++_counter}";
        await Task.Delay(1000); // simulate work
        Title = $"{ --_counter}";
        _semaphore.Release();
    }
}
Run Code Online (Sandbox Code Playgroud)

首次单击其他按钮后,将忽略单击,直到工作完成.Tittle可以是10.

这不起作用

void Button_Click(object sender, RoutedEventArgs e)
{
    if (_semaphore.Wait(0))
    {
        Test(); // moving code into separate method
        _semaphore.Release();
    }
}

async void Test()
{
    Title = $"{ ++_counter}";
    await Task.Delay(1000); // simulate work
    Title = $"{ --_counter}";
}
Run Code Online (Sandbox Code Playgroud)

点击按钮继续将上升Tittle2,3等.

我究竟做错了什么?

Mat*_*ero 5

async void只在事件处理程序中才有意义.这是一种特殊的异步现象.这意味着"火与忘".

你不想解雇并忘记这个Test()方法.你想等待它返回.

将您的Test签名更改为:

// Note that it returns a "Task". A task is an awaitable promise.
async Task Test()
{
   //...
}
Run Code Online (Sandbox Code Playgroud)

然后在您的事件处理程序上等待它:

async void Button_Click(object sender, RoutedEventArgs e)
{
     if (_semaphore.Wait(0))
     {
        await Test(); // moving code into separate method
        _semaphore.Release();
    }
}
Run Code Online (Sandbox Code Playgroud)