C# 是否过度使用异步等待?
我想知道我是否在代码中使用了C# 是否过度使用异步等待?,c#,.net,async-await,roslyn,C#,.net,Async Await,Roslyn,我想知道我是否在代码中使用了async和wait,以及这样做是否会造成(性能)损失 我经常做的事: static void Main() { var result = Task<int>.Run (()=> S1Async(1)).Result; Console.WriteLine(result); } static async Task<int> WrapperAsync(Func<int, Task<int>> func
async
和wait
,以及这样做是否会造成(性能)损失
我经常做的事:
static void Main()
{
var result = Task<int>.Run (()=> S1Async(1)).Result;
Console.WriteLine(result);
}
static async Task<int> WrapperAsync(Func<int, Task<int>> func) => await func(2);
static async Task<int> S1Async(int x) => await WrapperAsync(async t=> await S2Async(x * t));
static async Task<int> S2Async(int x) => await WrapperAsync(async t=> await S3Async(x * t));
static async Task<int> S3Async(int x) => await WrapperAsync(async t=> await S4Async(x * t));
static async Task<int> S4Async(int x) => await Task.FromResult(x * 10);
static void Main()
{
var result=Task.Run(()=>S1Async(1)).result;
控制台写入线(结果);
}
静态异步任务包装器异步(Func Func)=>wait Func(2);
静态异步任务S1Async(intx)=>await WrapperAsync(async t=>await S2Async(x*t));
静态异步任务S2Async(intx)=>await WrapperAsync(async t=>await S3Async(x*t));
静态异步任务S3Async(intx)=>await WrapperAsync(async t=>await S4Async(x*t));
静态异步任务S4Async(intx)=>等待任务.FromResult(x*10);
我认为可以跳过异步等待,并且此代码类似:
static void Main()
{
var result = Task<int>.Run(() => S1Async(1)).Result;
Console.WriteLine(result);
}
static Task<int> WrapperAsync(Func<int, Task<int>> func) => func(2);
static Task<int> S1Async(int x) => WrapperAsync(t => S2Async(x * t));
static Task<int> S2Async(int x) => WrapperAsync(t => S3Async(x * t));
static Task<int> S3Async(int x) => WrapperAsync(t => S4Async(x * t));
static Task<int> S4Async(int x) => Task.FromResult(x * 10);
static void Main()
{
var result=Task.Run(()=>S1Async(1)).result;
控制台写入线(结果);
}
静态任务包装器异步(Func Func)=>Func(2);
静态任务S1Async(intx)=>WrapperAsync(t=>S2Async(x*t));
静态任务S2Async(intx)=>wrappersync(t=>S3Async(x*t));
静态任务S3Async(intx)=>wrappersync(t=>S4Async(x*t));
静态任务S4Async(intx)=>Task.FromResult(x*10);
当任务嵌套在每个级别只有一个任务时,跳过异步/等待是否安全
两个代码示例在LinqPad中给出了相同的结果,因此我假设它们是相似的,但可能有一些副作用我应该注意到?简短的回答是:是的,在这种情况下可以跳过它们,是的,会有性能损失 当您的方法只需等待一次并立即返回时,如下所示:
async任务fooancy()
{
/* ... */
等待同步();
}
那么它就相当于写:
Task fooancy()
{
/* ... */
返回BarAsync();
}
async
的含义是(从fooancy
的角度来看):好的,操作BarAsync
可能需要一段时间才能完成,因此如果我们从中得到一个未完成的任务
,让我保存当前状态并将控制流返回给调用方。一旦任务
完成,我想重新开始状态并继续我一直在做的事情
在这种情况下,很明显,BarAsync
任务
完成后不会执行额外的工作,因此您可以将该任务
返回给调用者,因为实际上fooancy
完成的时间与任务
完成的时间完全相同。不需要保存任何状态或计划继续
当我们讨论单个调用时,这种方法的开销并不巨大,但是如果您多次调用这种方法,您可能会感到影响。当您将方法声明为async
时,编译器必须设置整个async
基础结构-状态机、连续调度、整个包。因此,一般来说:如果您可以将方法简化为非异步
,而只是返回另一个任务
,那么这样做是值得的
作为旁注:您当然不需要将S1Async
调用包装到任务中。运行,您就不必自C#7.1以来同步阻塞主
。你可以写:
static async Task Main()
{
var结果=等待S1Async(1);
控制台写入线(结果);
}
我想说,这段代码的最大问题是将异步等待与阻塞(使用Result
或Wait
)混合在一起,如果使用不当,这种做法可能会导致死锁。不使用async await,而是返回任务是可以的,只要您不在try块中执行此操作,因为如果您不await
,则在您离开try块后会引发异常。这是一种惩罚吗?你的问题是,如果这变得越来越慢,那么执行一切都是同步的吗?5个线程互相等待,你知道你在做什么…这没什么错。线程池正在处理,您一次启动的线程不会太多(但阈值超过100)。您可以使用2个线程使自己陷入死锁,而使用不小心编程的机会可能会增加到200个线程。在单核CPU上,async对同步执行的惩罚总是很小。但是单核CPU现在只存在于虚拟机上。在这里玩一下:你会看到两者之间的区别。差异的实际成本取决于您正在进行的计算,但如果“有用”代码与“开销”之间的关系不好,则差异可能会很大,