Joan Venge
Joan Venge

Reputation: 330862

How to parallellize/async this method?

I am trying to write this code in a way where it doesn't block the program. client.Spot.Market.GetKlinesAsync supports await but not sure how I can structure the code so that it can be awaited.

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 ( );
    }
}

What confuses me is how I can achieve this because I need to be able to compute the min and max values. So if I access Result, the function is executed immediately, right?

So I can't get my head around on how to achieve this computation in parallel.

Upvotes: 0

Views: 349

Answers (2)

Patrick Tucci
Patrick Tucci

Reputation: 1952

You don't need to do it in parallel to not block the UI. Just await the asynchronous method call. It's unclear exactly what GetKlinesAsync returns, but something like this would work without blocking the UI (assuming the method is IO-bound and assuming your calculations are reasonably fast):

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();
    }
}

If you wanted to run the calls in parallel to speed up the execution, you could, but this is not necessary to prevent the method call from blocking the calling thread.

Consider reading the Microsoft documentation on Task-based asynchronous programming. There are many gotchas ahead if you don't truly understand how Tasks, async and await work at a basic level.

Upvotes: 4

Serg
Serg

Reputation: 4666

Just create nested async operation to get min/max for single Coin, then run all in parallel:

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 ( );
}

The danger of such a approach may be that in case when you have really many Coins, you will create a big bunch of task at the single moment. If this is a case, then you can additionally perform some kind of partition of the work to the chunks of the appropriate size.

Upvotes: 7

Related Questions