使用Task.Run是一种不好的做法吗?

Jer*_*acs 7 c# asynchronous async-await

通常,在类上实现异步方法时,我写这样的东西:

public Task<Guid> GetMyObjectIdAsync(string objectName)
{
    return Task.Run(() => GetMyObjectId(objectName));
}

private Guid GetMyObjectId(string objectName)
{
    using (var unitOfWork = _myUnitOfWorkFactory.CreateUnitOfWork())
    {
        var myObject = unitOfWork.MyObjects.Single(o => o.Name == objectName);
        return myObject.Id;
    }
}
Run Code Online (Sandbox Code Playgroud)

这种模式允许我同步和异步地使用相同的逻辑,具体取决于具体情况(我的大多数工作都在旧的代码库中,而不是很多支持异步调用),因为我可以公开公开同步方法并得到如果需要,最大兼容性.

最近我读过一些SO帖子,建议使用Task.Run()是一个坏主意,只应在某些情况下使用,但这些情况似乎并不十分清楚.

我上面描述的模式实际上是个坏主意吗?我是否会以这种方式失去异步调用的某些功能/预期目的?或者这是一个合法的实施?

i3a*_*non 14

你正在做的是将同步操作卸载到另一个线程.如果你的线程是"特殊的",那就完全没问题了."特殊"线程的一个示例是UI线程.在这种情况下,您可能希望卸载它的工作以保持UI响应(另一个例子是某种监听器).

然而,在大多数情况下,您只是将工作从一个线程转移到另一个线程.这不会添加任何值,并且会增加不必要的开销.

所以:

我上面描述的模式实际上是个坏主意吗?

是的.将同步工作卸载到ThreadPool并假装它是异步的是一个坏主意.

我是否会以这种方式失去异步调用的某些功能/预期目的?

实际上,这个操作实际上并没有异步.如果您在远程计算机上执行此操作并且您可以从异步操作中获益,则操作本身需要是真正异步的,这意味着:

var myObject = await unitOfWork.MyObjects.SingleAsync(o => o.Name == objectName);
Run Code Online (Sandbox Code Playgroud)

您当前正在做的事情称为"异步过同步",您可能不应该这样做.更多内容我应该为同步方法公开异步包装器吗?

  • @CodeCaster:异步代码是这样的任何代码:(1)您要求计算,(2)由于某种原因计算需要一些时间,(3)在您等待时,您在此线程上运行其他代码,( 4)当结果可用时,您使用结果。实现异步的一种方法是将工作转移到其他线程上,但没有*要求*以这种方式实现异步。就像您在做早餐时要求雇一名煮鸡蛋的厨师和一名烤面包的厨师一样。 (2认同)

Eri*_*ert 10

最近我读过一些SO帖子,建议使用Task.Run()是一个坏主意,只应在某些情况下使用,但这些情况似乎并不十分清楚.

绝对简单的经验法则我告诉那些不熟悉异步的人是:

首先,了解目的.异步用于缓解高延迟操作的重要低效率.

你正在做低延迟的事情吗?然后不要以任何方式使它异步.做这个工作吧.它很快.使用工具来缓解低延迟任务的延迟只会使您的程序变得不必要地复杂化.

您正在进行高延迟的事情,因为它正在等待磁盘旋转或数据包显示?使这个异步,但不要把它放在另一个线程上.你不雇佣工人坐在你的邮箱旁等待信件到达; 邮政系统已经异步运行给你了.您不需要雇用人员来使其更加异步.如果不清楚,请阅读"没有线程".

高延迟工作是否等待CPU进行大量计算?就像计算需要超过10毫秒?然后将该任务卸载到线程上,以便可以将线程调度到空闲CPU.