2017-09-17 44 views
0

我的意思是说,我们有一个异步方法Task<string> CalculateSha256(string s)。是否有可能,线程#1和线程#2的调用连续执行被认为是同时执行的,没有线程#1和#2知道对方的任何事情吗?例如,我有一个控制器,是否有可能在不同的线程上等待任务完成?

public async Task<string> Get(string value) 
{ 
    return await CalculateSha256(value); 
} 

,我想两个不同的请求访问的代码块这是负责计算(CalculateSha256)连续。

+0

这是一个不同的问题,因为这两个线程不应该等待**相同的**任务,但是,为了继续,应该等待另一个线程的结束。 – nicks

+0

你能展示你想要达到的目标吗?也许任务的'ContinueWith()'可能是一个答案?或者'TaskCompletionSource'类? – orhtej2

回答

4

您需要同步对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); 
    } 
} 
+0

如果您概括您的答案,以便它可以为任何'任务'工作,您可以在将来得到更多upvotes –

+0

@ L.B感谢您的提示,请参阅我的编辑:) – YuvShap