SemaphoreSlim和async / await

时间:2016-10-25 12:18:58

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

首次点击后,点击将被忽略,直到工作完成。 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}";
}

持续点按按钮会使Tittle升至23,依此类推。

我做错了什么?

1 个答案:

答案 0 :(得分:5)

async void仅在事件处理程序中有意义。这是一种特殊的异步现象。这意味着“火与忘记”。

您不想触发并忘记Test()方法。你想等待它回来。

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