【问题标题】:Way to creating async wrapper创建异步包装器的方法
【发布时间】:2014-12-30 06:38:10
【问题描述】:

如何更好地为同步方法创建异步包装器?

// sync method
public void LongOperation()
{
    //code...
}


// versions of wrapper
public async Task LongOpertionWrapperAsyncV1()
{
    var task = Task.Factory.StartNew(LongOperation);
    await task.ConfigureAwait(false);
}

public Task LongOpertionWrapperAsyncV2()
{
    var task = Task.Factory.StartNew(LongOperation);
    task.ConfigureAwait(false);
    return task;
}

虽然两个版本的使用没有区别。

async Task Executor()
{
    await LongOpertionWrapperAsyncV1();
    await LongOpertionWrapperAsyncV2();
}

对于返回值的方法(Task),我使用第一个版本。

但我想知道你的意见。

这些版本之间有普遍的区别吗?

【问题讨论】:

标签: c# .net async-await c#-5.0


【解决方案1】:

您应该使用“类似”V2:

public Task LongOpertionWrapperAsyncV2()
{
    return Task.Run(LongOperation);
}

async Task Executor()
{
    await LongOpertionWrapperAsyncV2().ConfigureAwait(false);
}

与 V1 相比,这为您节省了一次上下文切换。只要您不需要“等待另一个操作”并且异步任务是方法中的最后一个操作,您就可以返回任务而不是等待它并将等待留给调用者(也可以或不能添加ConfigureAwait)。

Task.Factory.StartNew 仅在您想像 HPT 建议的那样提供 TaskCreationOptions.LongRunning 时才需要。

更新:
正如斯蒂芬已经说过的那样:在极少数情况下你应该这样做async over sync(但有)。所以在实施这样的事情之前想想你到底在做什么。简而言之:如果是 CPU-bound 的工作不要做,如果是某种“等待 IO”可能就做。
我们在这里有一个案例,我们开发了一个“几乎一路异步”的库,用于控制不同的硬件设备。整个“通用库”是异步的,但一些低级设备驱动程序和/或访问库不支持async,所以在最低级别我们执行以下操作:

public Task<byte[]> ReadAsync(int length)
{
    return Task.Run(() => hwDevice.Read(length));
}

hwDevice.Read 仍然会锁定线程,但不会锁定 CPU,因此在我们等待 IO 的那段时间 UI 是响应式的(在“实时”中也有一些取消和错误处理逻辑) .

【讨论】:

  • async 关键字在 ReadAsync 示例代码中是否有任何用途?我问是因为它不做await(这当然是有道理的)。
【解决方案2】:

Neither solution is correct。最好的答案是为同步代码公开异步方法。我更深入地探讨了“为什么”on my blog

如果您的代码是异步的,则使用asyncawait。如果不是,那就不要。应该由调用者决定如何调用代码(例如,使用Task.Run)。

【讨论】:

  • 是否有正确的方法将应该异步的同步方法包装为异步?即假设您有同步方法 GetDatabaseData();由于数据库调用是 I/O 绑定的,有没有办法使这个异步?
  • @Mackers:不。如果方法不是异步的,则无法“使”它异步(当然,除非您修改实现)。
  • @StephenCleary 我已阅读您的“不要阻止异步”帖子。如果我想制作异步方法的同步包装器怎么办?我应该在我的同步方法(异步包装器)中使用ConfigureAwait 吗?
  • 最佳答案是"you shouldn't expose synchronous wrappers for asynchronous methods"。如果您确实需要,请使用我的 article on brownfield async 中描述的 bool 参数 hack。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-26
  • 2011-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多