0

How to run an async Task without blocking other tasks?

I have one function that iterates though a List but the problem is that when the function is called other functions won't work again until the first function is done. What are the ways of making the HandleAsync function non-blocking ?

   public static async Task HandleAsync(Message message, TelegramBotClient bot)
    {
        await Search(message, bot); // This should be handled without working other possible functions. I have a function similar to this but which doesn't iterate though any list.
    }

private static async Task Search(Message message, TelegramBotClient bot)
{
    var textSplit = message.Text.Split(new[] {' '}, 2);

    if (textSplit.Length == 1)
    {
        await bot.SendTextMessageAsync(message.From.Id, "Failed to fetch sales. Missing game name. ",
            ParseMode.Html);
    }
    else
    {
        var search = await Program.itad.SearchGameAsync(textSplit[1], limit: 10, cts: Program.Cts);

        if (search.Data != null)
        {
            var builder = new StringBuilder();
            foreach (var deal in search.Data.List)
            {
                var title = deal.Title;
                var plain = deal.Plain;
                var shop = deal.Shop != null ? deal.Shop.Name : "N/A";
                var urls = deal.Urls;

                var priceNew = deal.PriceNew;
                var priceOld = deal.PriceOld;
                var priceCut = deal.PriceCut;

                builder.AppendLine($"<b>Title:</b> {title}");
                builder.AppendLine($"<b>Shop:</b> {shop}");
                builder.AppendLine();
                builder.AppendLine($"<b>Price:</b> <strike>{priceOld}€</strike> | {priceNew}€ (-{priceCut}%)");

                var buttons = new[]
                {
                    new[]
                    {
                        InlineKeyboardButton.WithUrl("Buy", urls.Buy.AbsoluteUri),
                        InlineKeyboardButton.WithUrl("History",
                            urls.Game.AbsoluteUri.Replace("info", "history"))
                    }
                };

                var keyboard = new InlineKeyboardMarkup(buttons);

                var info = await Program.itad.GetInfoAsync(plain, cts: Program.Cts);
                var image = info.Data.GameInfo.Image;

                if (image == null) image = new Uri("https://i.imgur.com/J7zLBLg.png");

                await TelegramBot.Bot.SendPhotoAsync(message.From.Id, new InputOnlineFile(image.AbsoluteUri),
                    builder.ToString(), ParseMode.Html, replyMarkup: keyboard,
                    cancellationToken: Program.Cts.Token);
                builder.Clear();
            }
        }
        else
        {
            await bot.SendTextMessageAsync(message.From.Id, "Failed to fetch sales. Game not found. ",
                ParseMode.Html);
        }
    }
  • Do you know where it is blocking? Can you do a break all and see what line it is blocked on? Usually if there is a deadlock in an async Task it has something to do with the UI thread being deadlocked. Is HandleAsync being called from a UI thread, or is anything inside of Search scheduling calls on the UI thread? – TJ Rockefeller Apr 29 '20 at 16:11
  • Well I tried removing the for each loop and add a Task.Delay(10000) but the loop is still blocking other functions. It couldn't be from the code inside the for loop – nitanmarcel Apr 29 '20 at 16:13
  • 2
    What do you mean it's blocking them? How are you calling HandleAsync? Is it deadlocked, or is it just not executing other functions until HandleAsync is done? – TJ Rockefeller Apr 29 '20 at 16:14
  • 3
    Do you want to execute your foreach loop in parallel then? Have a look at https://stackoverflow.com/questions/35126393/async-await-and-parallel and https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/how-to-make-multiple-web-requests-in-parallel-by-using-async-and-await – Slate Apr 29 '20 at 16:15
  • can you show the code where the method `HandleAsync` is being called? – zafar Apr 29 '20 at 16:18
  • I'm using Telegram.Bot library. Here is where Search is called: https://del.dog/Updates.cs , https://del.dog/TelegramBot.cs – nitanmarcel Apr 29 '20 at 16:20
  • 1
    Agreed, please define more clearly what you mean by "blocking", exactly? – ADyson Apr 29 '20 at 16:35
  • Your code still doesn't give the idea about how it is being called from the Main/UI thread, may be you need to share the Main method or something – zafar Apr 29 '20 at 16:37
  • The code that is needed, but is not shown here is your function that iterates through a list and calls `HandleAsync` Most likely you need to change how `HandleAsync` is called, not how `HandleAsync` is implemented. – TJ Rockefeller Apr 29 '20 at 16:38
  • In the del.dog/Updates.cs `BotOnMessageReceived` takes care of triggering the function when the message "/search" is sent. But when the HandleAsync function is working the other one which is bound to "/start" runs only after the HandleAsync function is completed. – nitanmarcel Apr 29 '20 at 16:39
  • Probably that is down to how the Bot class uses the methods. we can't see how the BotOnmessagereceived method is used, I don't think (correct me if I'm wrong). But each time it runs, it chooses either start or search depending on the received value. So whether they can run in parallel will likely depend on whether BotOnMessageReceived gets called in parallel, or gets awaited – ADyson Apr 29 '20 at 18:17
  • Yes you're right. Anyway I've gone thought some changes and now the switch returns the command handling functions instead of awaiting them since I don't really do anything else after triggering them. Is this a good practice or I should change it asap? My new Update.cs https://del.dog/Updates.cs and my new TelegramBot.cs https://del.dog/TelegramBot.cs @ADyson – nitanmarcel Apr 29 '20 at 19:13
  • Whether that's a good idea, well, again, it really depends what the calling code does with it. But the odds are it probably doesn't do any harm. It probably doesn't give any advantage though either. If the calling code awaits your tasks, then whether you await them or not is largely irrelevant. – ADyson Apr 29 '20 at 19:28

0 Answers0