Search code examples
.netasync-awaittaskservicecontroller

How do do an async ServiceController.WaitForStatus?


So ServiceController.WaitForStatus is a blocking call. How can it be done Task/Async manner?


Solution

  • The code for ServiceController.WaitForStatus is:

    public void WaitForStatus(ServiceControllerStatus desiredStatus, TimeSpan timeout)
    {
        DateTime utcNow = DateTime.UtcNow;
        this.Refresh();
        while (this.Status != desiredStatus)
        {
            if (DateTime.UtcNow - utcNow > timeout)
            {
                throw new TimeoutException(Res.GetString("Timeout"));
            }
            Thread.Sleep(250);
            this.Refresh();
        }
    }
    

    This can be converted to a task based api using the following:

    public static class ServiceControllerExtensions
    {
        public static async Task WaitForStatusAsync(this ServiceController controller, ServiceControllerStatus desiredStatus, TimeSpan timeout)
        {
            var utcNow = DateTime.UtcNow;
            controller.Refresh();
            while (controller.Status != desiredStatus)
            {
                if (DateTime.UtcNow - utcNow > timeout)
                {
                    throw new TimeoutException($"Failed to wait for '{controller.ServiceName}' to change status to '{desiredStatus}'.");
                }
                await Task.Delay(250)
                    .ConfigureAwait(false);
                controller.Refresh();
            }
        }
    }
    

    Or with support for a CancellationToken

    public static class ServiceControllerExtensions
    {
        public static async Task WaitForStatusAsync(this ServiceController controller, ServiceControllerStatus desiredStatus, TimeSpan timeout, CancellationToken cancellationToken)
        {
            var utcNow = DateTime.UtcNow;
            controller.Refresh();
            while (controller.Status != desiredStatus)
            {
                if (DateTime.UtcNow - utcNow > timeout)
                {
                    throw new TimeoutException($"Failed to wait for '{controller.ServiceName}' to change status to '{desiredStatus}'.");
                }
                await Task.Delay(250, cancellationToken)
                    .ConfigureAwait(false);
                controller.Refresh();
            }
        }
    }