死锁和全程异步

问题描述 投票:0回答:1

在与同事讨论一段代码时,出现了一些关于其可靠性的问题。具体争论点在于

Task.Run
方法中
Task.WhenAll
CreateAxelAsync
的使用。

我就开门见山吧。我对下面的代码有两个问题:

  1. 容易出现死锁吗?
  2. 它是否打破了异步所有原则?
public record Vehicle( Axel FrontAxel, Axel RearAxel ) { }
    
public record Axel( IList<Wheel> Wheels ) { }
    
public record Wheel( float TirePressure ) { }
    
public static class VehicleFactory
{
   // async
   public static async Task<Vehicle> CreateAsync( int wheelsPerAxel )
   {
      var frontAxelTask = CreateAxelAsync( wheelsPerAxel );
      var rearAxelTask = CreateAxelAsync( wheelsPerAxel );
    
      await Task.WhenAll( frontAxelTask, rearAxelTask );
    
      return new Vehicle( frontAxelTask.Result, rearAxelTask.Result );
   }
   
   // async
   private static async Task<Axel> CreateAxelAsync( int wheelsPerAxel )
   {
      var wheelTasks = new Task<Wheel>[ wheelsPerAxel ];
    
      for ( int i = 0; i < wheelsPerAxel; i++ )
      {
         int wheelIndex = i;
         wheelTasks[ i ] = Task.Run( () => CreateWheel( wheelIndex ) );
      }
    
      Wheel[] wheels = await Task.WhenAll( wheelTasks );
    
      return new Axel( wheels );
   }
   
   // sync
   private static Wheel CreateWheel( int wheelIndex )
   {
      float tirePressure = CalculateTirePressure( wheelIndex );
      return new Wheel( tirePressure );
   }
   
   // sync
   private static float CalculateTirePressure( int wheelIndex )
   {
      float tirePressure;
      // perform some CPU-bound processing and assign to tirePressure
      return tirePressure;
   }
}
c# asynchronous async-await
1个回答
0
投票

我假设您专门询问这一行,因为它使用

Result
:

return new Vehicle( frontAxelTask.Result, rearAxelTask.Result );

在这种情况下,任务“已经完成”,因此不存在结果陷入僵局的危险。同样,由于任务已经异步完成,因此它不会阻塞异步代码;它一直在异步进行。 也就是说,我(个人)更喜欢使用

await

来提取结果:要么

await
每个任务,要么将
await Task.WhenAll
结果分配给局部变量并从那里获取结果。这是因为,如果删除
WhenAll
,相同的代码也会编译,但它
is
容易出现死锁,并且does违反异步所有方式。

© www.soinside.com 2019 - 2024. All rights reserved.