SemaphoreSlim 和 async/await

SemaphoreSlim and async/await

这个有效:

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();
    }
}

在第一次点击之后,其他按钮的点击将被忽略,直到工作完成。 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}";
}

连续点击按钮会上升Tittle23等。

我做错了什么?

async void 仅在事件处理程序中有意义。它是一种特殊类型的异步。意思是"fire and forget".

你不想开火而忘记 Test() 方法。你想等到 return.

将您的 Test 签名更改为:

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

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

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