kempyyyy
kempyyyy

Reputation: 224

Call a process asynchronously via WebAPI

I am in a scenario wherein I need to call an exe process via an API endpoint (fire and forget). However, the exe that I will call is a long running one but I need to wait for it to finish to execute further codes. This will happen in the background and the client shouldn't really wait for it. When I'm trying the code below, the call is waiting for the exe process to finish. I've also tried making the method "async" but still same result.

    [HttpPost]
    public async Task<bool> ToggleCarWeaverService(string command)
    {
        try
        {
            var fileName = @"SomeExe.exe";
            await _service.RunProcessAsync(command, fileName);
            return true;

        }
        catch (Exception ex)
        {
            throw new HttpResponseException(HttpStatusCode.InternalServerError);
        }
    }


    public Task<int> RunProcessAsync(string command, string fileName)
    {
        // Use ProcessStartInfo class
        ProcessStartInfo startInfo = new ProcessStartInfo
        {
            CreateNoWindow = false,
            UseShellExecute = true,
            FileName = fileName,
            WindowStyle = ProcessWindowStyle.Normal,
            Arguments = command
        };

        try
        {
            var tcs = new TaskCompletionSource<int>();

            var process = new Process
            {
                StartInfo = startInfo,
                EnableRaisingEvents = true
            };

            process.Exited += (sender, args) =>
            {
                tcs.SetResult(process.ExitCode);
                //Do more code
                process.Dispose();

            };

            process.Start();

            return tcs.Task;
        }
        catch (Exception ex)
        {
            // Log error.
            throw ex;
        }
    }

Upvotes: 1

Views: 1168

Answers (3)

Paul Michaels
Paul Michaels

Reputation: 16705

The answers given here will, correctly, answer your question - that is, by not awaiting the result, your call will return immediately. However, there is no guarantee that the process will continue to run. Once you've left the function you, effectively, have a rouge process that may or may not complete.

Most Cloud providers have a solution to this (e.g. Azure WebJobs), or you could roll your own using something like HangFire.

Upvotes: 2

Nkosi
Nkosi

Reputation: 247571

Do not await the async task.

Use Task.Run to wrap and continue

[HttpPost]
public IHttpActionResult ToggleCarWeaverService(string command) {
    Task.Run(async () => {
        var fileName = @"SomeExe.exe";
        await _service.RunProcessAsync(command, fileName);
        //...other code after process finish
    });
    return Ok();
}

Upvotes: 2

Rahul
Rahul

Reputation: 77926

Then you shouldn't await the call further at all and thus change the line where you await the call RunProcessAsync to

_service.RunProcessAsync(command, fileName);

Upvotes: 1

Related Questions