您需要同步对CalculateSha256方法的访问,以便一次只有一个线程执行它。
由于lock
声明does not play nicely with async您可以使用SemaphoreSlim
类。
只要将其添加为一个静态字段到控制器:
private static readonly SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(1, 1);
而在你的动作使用WaitAsync方法(不要忘了释放它,当你完成,使用finally块):
public async Task<string> Get(string value)
{
await _semaphoreSlim.WaitAsync();
try
{
return await CalculateSha256(value);
}
finally
{
_semaphoreSlim.Release();
}
}
如果您发现这种方法非常有用,你不喜欢reapeat在try finally块,你可以创建一个基控制器类与受保护的通用助手:
protected async Task<T> GetConsecutively(Func<Task<T>> taskFactory)
{
await _semaphoreSlim.WaitAsync();
try
{
return await taskFactory();
}
finally
{
_semaphoreSlim.Release();
}
}
并修改Get方法lambda表达式传递给它:
public async Task<string> Get(string value)
{
return await GetConsecutively(() => CalculateSha256(value));
}
或者选择使用斯蒂芬·克利里的AsyncLock
代替SemaphoreSlim
支持高层次的API接近lock
声明:
private static readonly AsyncLock _asyncLock = new AsyncLock();
public async Task<string> Get(string value)
{
//Notice the use of using block
//instead of try and finally
using(await _asyncLock.LockAsync())
{
return await CalculateSha256(value);
}
}
这是一个不同的问题,因为这两个线程不应该等待**相同的**任务,但是,为了继续,应该等待另一个线程的结束。 – nicks
你能展示你想要达到的目标吗?也许任务的'ContinueWith()'可能是一个答案?或者'TaskCompletionSource'类? – orhtej2