【问题标题】:Is it possible to await task completion on different threads? [duplicate]是否可以在不同的线程上等待任务完成? [复制]
【发布时间】:2018-02-26 02:51:36
【问题描述】:

我的意思是,假设我们有一个异步方法Task<string> CalculateSha256(string s)。线程#1 和线程#2 的调用是否有可能连续 执行,而不是同时执行,而线程#1 和#2 不知道彼此的任何信息?例如,我有一个控制器,

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

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

【问题讨论】:

  • 这是一个不同的问题,因为这两个线程不应该等待相同的任务,但是,一个应该等待另一个结束,以便继续。跨度>
  • 你能展示你想要达到的目标吗?也许Task的ContinueWith()可能是一个答案?还是TaskCompletionSource 班级?

标签: c# .net multithreading async-await task-parallel-library


【解决方案1】:

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

如果您发现这种方法很有用并且您不喜欢重复 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));
}

或者使用 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&lt;T&gt; ,您将来可以获得更多支持
  • @L.B 感谢您的提示,请参考我的编辑 :)
猜你喜欢
  • 1970-01-01
  • 2022-01-02
  • 2011-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多