Home > front end >  My async task is blocking other code from running and not outputting anything
My async task is blocking other code from running and not outputting anything

Time:01-26

Recently I've been converting my node.js bot to C# but I've ran across an problem for some odd reason public async Task InitCloudCompute() is blocking my other code from running. I got no idea why this is happening and I am fairly new with C#. I would appreciate it if someone could help me solve this issue out. :)

Edit: I forgot to say the program starts because I can open the localhost in my browser.

using System;
using System.Diagnostics;
using System.Reflection;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using Microsoft.Extensions.DependencyInjection;
using static Doom.Grid.Bot.Utility.ConsoleGlobals;

namespace Doom
{
    class Program
    {
        static void Main(string[] args) => new Program().InitBotAsync()
            .GetAwaiter().GetResult();
        
        private DiscordSocketClient _client;
        private CommandService _commands;
        private IServiceProvider _services;

        public async Task InitBotAsync()
        {
            _client = new DiscordSocketClient();
            _commands = new CommandService();
            _services = new ServiceCollection()
                .AddSingleton(_client)
                .AddSingleton(_commands)
                .BuildServiceProvider();

            _client.Log  = _client_internal_Log;

            await InitCloudCompute();
            await RegisterCommandsAsync();
            await _client.LoginAsync(TokenType.Bot, "Nope"); // TODO: Remove 
                // hard-coded token
            await _client.StartAsync();
            await Task.Delay(-1);
        }

        public async Task InitCloudCompute()
        {
            Console.WriteLine($"{CCServiceInternalLog} Initializing CCService");
            ProcessStartInfo processStartInfo;
            Process process;

            processStartInfo = new ProcessStartInfo
            {
                CreateNoWindow = true,
                RedirectStandardOutput = true,
                RedirectStandardInput = true,
                UseShellExecute = false,
                Arguments = "-console -verbose 5000",
                FileName = "D:\\21CC\\CC-FE4FEB09A756\\CCService.exe"
            };

            process = new Process
            {
                StartInfo = processStartInfo,
                EnableRaisingEvents = true
            };

            process.OutputDataReceived  = new DataReceivedEventHandler
            (
                delegate (object sender, DataReceivedEventArgs e)
                {
                    Console.WriteLine($"{CCServiceInternalLog} {e.Data.ToString()}");
                }
            );

            process.Start();
            process.BeginOutputReadLine();
            process.WaitForExit();
            process.CancelOutputRead();
        }

        private Task _client_internal_Log(LogMessage arg)
        {
            Console.WriteLine($"{DiscordInternalLog} {arg}");
            return Task.CompletedTask;
        }

        public async Task RegisterCommandsAsync()
        {
            _client.MessageReceived  = HandleCommandAsync;
            await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
        }

        private async Task HandleCommandAsync(SocketMessage arg)
        {
            var message = arg as SocketUserMessage;
            var context = new SocketCommandContext(_client, message);
            if (message.Author.IsBot) return;

            int argPos = 0;
            if (message.HasStringPrefix(">", ref argPos))
            {
                var result = await _commands.ExecuteAsync(context, argPos, _services);
                if (!result.IsSuccess) Console.WriteLine(result.ErrorReason);
            }
        }
    }
}

CodePudding user response:

According to the docs here https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.waitforexit?view=net-6.0 Process.WaitForExit will block the current thread.

"Sets the period of time to wait for the associated process to exit, and blocks the current thread of execution until the time has elapsed or the process has exited. To avoid blocking the current thread, use the Exited event."

Docs for Task.GetAwaiter similarly say that it is generally for the compiler and not for application use. https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.getawaiter?view=net-6.0

So you could create a new task and run it like so

Task task = Task.Run({new Program().InitBotAsync()});

And instead of process.WaitForExit() try

process.Exited = new EventHandler(yourHandlerHere);

to do the cleanup

  •  Tags:  
  • Related