ServiceController.WaitForStatus with multiple desiredStatus

本文关键字:desiredStatus multiple with WaitForStatus ServiceController | 更新日期: 2023-09-27 17:56:54

我目前使用以下方法等待服务启动...

srvCtl.Start();
srvCtl.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 30))

如果服务在启动后立即停止,我也想解释它被停止的原因。

有没有办法同时等待ServiceControllerStatus.RunningServiceControllerStatus.Stopped

ServiceController.WaitForStatus with multiple desiredStatus

以下内容可能有点问题,因为任务和线程彼此不太喜欢,但你可以这样做:

CancellationTokenSource cts = new CancellationTokeSource();
List<Task> tasks = new List<Task>
{
    Task.Run(()= > srvCtl.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 30)), cts),
    Task.Run(()= > srvCtl.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 30)), cts),
    ...
}
// When any of the tasks completes, it means the service reached on of the statuses you were tracking
await Task.WhenAny(tasks);
// To cancel the rest of the tasks that are still waiting
cts.Cancel();

希望对您有所帮助!

如果时间跨度在启动之前过期,则 WaitforStatus 会引发超时异常。

您可以在异常处理程序中检查当前和所需状态,并在那里执行您认为合适的任何操作。如果设置的超时足够小,则可以进行测试,然后根据需要退出或重试。

我不相信 WaitforStatus 支持多个同时条件,但让它过期,然后检查似乎非常接近您想要的。

事实证明,ServiceController.WaitForStatus除了每 0.25 秒检查一次服务是否处于所需状态外,什么也不做。(来源:.NET Framework 代码的反编译。因此,如果您尝试等待瞬态,您可能会错过它。因此,创建多个任务(和线程)来等待每个状态是矫枉过正的;只需重现实际的 .NET 代码并更改返回条件即可。

    public static ServiceControllerStatus WaitForStates(this ServiceController service, TimeSpan timeout, params ServiceControllerStatus[] states)
    {
        //parameter checks omitted
        DateTime start = DateTime.UtcNow;
        while (true)
        {
            service.Refresh();
            ServiceControllerStatus currentState = service.Status;
            if (states.Contains(currentState))
                return currentState;
            TimeSpan elapsedTime = DateTime.UtcNow - start;
            if (elapsedTime > timeout)
                throw new TimeoutException();
            Thread.Sleep(250);
        }
    }