【问题标题】:How to parallellize/async this method?如何并行化/异步此方法?
【发布时间】:2021-08-01 14:38:22
【问题描述】:

我正在尝试以不会阻塞程序的方式编写此代码。 client.Spot.Market.GetKlinesAsync 支持等待,但不知道如何构造代码以便等待它。

public static async Task GetMinMaxValues ( BinanceClient client, ObservableCollection<Coin> coins )
{
    foreach ( var coin in coins )
    {
        var task = client.Spot.Market.GetKlinesAsync ( coin.SymbolPair, KlineInterval.OneDay );
        coin.MinVal = klines.Result.Data.Select ( k => k.Low ).Min ( );
        coin.MaxVal = klines.Result.Data.Select ( k => k.High ).Max ( );
    }
}

让我感到困惑的是如何实现这一点,因为我需要能够计算最小值和最大值。所以如果我访问Result,函数会立即执行,对吧?

所以我不知道如何并行实现这种计算。

【问题讨论】:

    标签: c# .net performance asynchronous async-await


    【解决方案1】:

    只需创建嵌套异步操作以获取单个 Coin 的最小值/最大值,然后并行运行:

    public static async Task GetMinMaxValues ( BinanceClient client, 
                                         ObservableCollection<Coin> coins )
    {
        await Task.WhenAll(coins.Select(async c=>await GetMinMax(c, client)).ToList());
    }
    
    public static async Task GetMinMax(Coin coin, BinanceClient client)
    {
        var res = await client.Spot.Market.GetKlinesAsync ( coin.SymbolPair );
        coin.MinVal = klines.Result.Data.Select ( k => k.Low ).Min ( );
        coin.MaxVal = klines.Result.Data.Select ( k => k.High ).Max ( );
    }
    

    这种方法的危险可能是,如果你有很多Coins,你会在一个时刻创建一大堆任务。如果是这种情况,那么您可以另外对工作进行某种分区,以适当大小的块。

    【讨论】:

      【解决方案2】:

      您无需并行执行即可不阻塞 UI。只需await 异步方法调用。尚不清楚 GetKlinesAsync 究竟返回了什么,但这样的事情不会阻塞 UI(假设该方法受 IO 限制并且假设您的计算相当快):

      public static async Task GetMinMaxValues(BinanceClient client, ObservableCollection<Coin> coins)
      {
          foreach (var coin in coins)
          {
              //Invokes asynchronous get method, waits for it to finish, and gets the result
              var result = await client.Spot.Market.GetKlinesAsync(coin.SymbolPair, KlineInterval.OneDay);
              //Use the result to set your coin values
              coin.MinVal = result.Data.Select(k => k.Low).Min();
              coin.MaxVal = result.Data.Select(k => k.High).Max();
          }
      }
      

      如果您想并行运行调用以加快执行速度,您可以这样做,但这不是防止方法调用阻塞调用线程所必需的。

      考虑阅读Task-based asynchronous programming 上的 Microsoft 文档。如果您不真正了解Tasksasyncawait 的基本工作原理,那么您将面临许多陷阱。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-24
        • 1970-01-01
        相关资源
        最近更新 更多