是否可以在不同线程上等待任务完成?
Is it possible to await task completion on different threads?
我的意思是,假设我们有一个异步方法 Task<string> CalculateSha256(string s)
。来自线程 #1 和线程 #2 的调用是否有可能 连续执行 而不是并发执行,而线程 #1 和 #2 彼此一无所知?比如我有一个控制器,
public async Task<string> Get(string value)
{
return await CalculateSha256(value);
}
我想要两个不同的请求来连续访问负责计算的代码块 (CalculateSha256)。
您需要同步访问 CalculateSha256 方法,一次只有一个线程执行它。
由于 lock
语句 does not play nicely with async you can use SemaphoreSlim
class.
只需将其作为静态字段添加到您的控制器即可:
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();
}
}
如果您发现这种方法有用并且您不喜欢重复 try finally 块,您可以创建一个带有受保护的通用助手的基本控制器 class:
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));
}
或者使用 Stephen Cleary 的 AsyncLock
而不是 SemaphoreSlim
,后者支持更接近 lock
语句的高级 API:
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);
}
}
我的意思是,假设我们有一个异步方法 Task<string> CalculateSha256(string s)
。来自线程 #1 和线程 #2 的调用是否有可能 连续执行 而不是并发执行,而线程 #1 和 #2 彼此一无所知?比如我有一个控制器,
public async Task<string> Get(string value)
{
return await CalculateSha256(value);
}
我想要两个不同的请求来连续访问负责计算的代码块 (CalculateSha256)。
您需要同步访问 CalculateSha256 方法,一次只有一个线程执行它。
由于 lock
语句 does not play nicely with async you can use SemaphoreSlim
class.
只需将其作为静态字段添加到您的控制器即可:
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();
}
}
如果您发现这种方法有用并且您不喜欢重复 try finally 块,您可以创建一个带有受保护的通用助手的基本控制器 class:
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));
}
或者使用 Stephen Cleary 的 AsyncLock
而不是 SemaphoreSlim
,后者支持更接近 lock
语句的高级 API:
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);
}
}