上下文:原始聊天机器人。
我有一个简单的代码:
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也不是很好的选择。
这些情况通常如何处理?
答案 0 :(得分:0)
您最好查看SemaphoreSlim
和Interlocked.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时,它才会产生可在其他地方运行的其他东西。所以根本不需要使用锁。