为什么windows服务OnStart()中的Task.Run()会导致服务拒绝停止?
Why does Task.Run() in windows service OnStart() cause the service to refuse to stop?
我不确定为什么此服务拒绝停止。
我 运行 试图纠正启动服务时抛出的 TimeoutException
。使用:
public void OnStart()
{
_startTask = Task.Run(DoWork, _cancelTokenSource.Token);
}
private void DoWork(){ [listen for things and operate on them] }
public void OnStop()
{
_cancelTokenSource.Cancel();
_startTask.Wait();
}
我知道实现一个简单的计时器可以解决这个问题,但这不是我要问的重点。为什么使用 Task.Run(() => action, _tokenSource.Token)
解决了 TimeoutException
但导致服务不响应控制消息?
观察到的问题
安装并启动服务后(顺便说一句,它是 TopShelf),我无法通过常规方法停止服务。
第一次尝试:
所有后续尝试:
编辑:还是不开心
这是我在遵循 provided example 之后的尝试。
public void Start()
{
var token = _cancelTokenSource.Token;
Task.Factory.StartNew(() => Setup(token), token);
}
public void Stop()
{
_cancelTokenSource.Cancel();
//TearDown(); <-- original implementation of stop
}
private void Setup(CancellationToken token)
{
_mailman.SendServiceStatusNotification(_buildMode, "Started");
... create some needed objects
token.Register(TearDown);
InitializeInboxWatcherProcess(...);
}
private void TearDown()
{
_inboxWatcher.Terminate();
_mailman.SendServiceStatusNotification(_buildMode, "Stopped");
}
private void InitializeInboxWatcherProcess(...)
{
// pre create and initiate stuff
_inboxWatcher = new LocalFileSystemWatcherWrapper(...);
_inboxWatcher.Initiate();
}
public class LocalFileSystemWatcherWrapper : IFileSystemWatcherWrapper
{
// do FileSystemWatcher setup and control stuff
}
这很可能是因为您没有取消方法,或者在您调用 Cancel()
时 DoWork()
中的子进程仍然 运行。正如@Damien_The_Unbeliever所说,取消是一项合作任务。
当你调用_cancelTokenSource.Cancel()
时,如果你还没有注册一个回调函数,所有发生的事情就是一个布尔值isCancellationRequested
被设置为true,然后DoWork()
方法负责看到这一点并自行停止执行。但是,这里有一个缺陷,您可能会说,如果调用 Cancel()
时 DoWork()
任务中有一个耗时的循环 运行,则该循环将必须完成在它可以检查 isCancellationRequested
的值之前的迭代,这可能导致挂起。
解决方法是在 DoWork()
方法中插入取消回调函数,参见 here 然后将它们注册到令牌中,这样当您调用 Cancel()
方法时,后台的所有任务 运行 都已停止,无需等待它们。
希望对您有所帮助!
我不确定为什么此服务拒绝停止。
我 运行 试图纠正启动服务时抛出的 TimeoutException
。使用:
public void OnStart()
{
_startTask = Task.Run(DoWork, _cancelTokenSource.Token);
}
private void DoWork(){ [listen for things and operate on them] }
public void OnStop()
{
_cancelTokenSource.Cancel();
_startTask.Wait();
}
我知道实现一个简单的计时器可以解决这个问题,但这不是我要问的重点。为什么使用 Task.Run(() => action, _tokenSource.Token)
解决了 TimeoutException
但导致服务不响应控制消息?
观察到的问题
安装并启动服务后(顺便说一句,它是 TopShelf),我无法通过常规方法停止服务。
第一次尝试:
所有后续尝试:
编辑:还是不开心
这是我在遵循 provided example 之后的尝试。
public void Start()
{
var token = _cancelTokenSource.Token;
Task.Factory.StartNew(() => Setup(token), token);
}
public void Stop()
{
_cancelTokenSource.Cancel();
//TearDown(); <-- original implementation of stop
}
private void Setup(CancellationToken token)
{
_mailman.SendServiceStatusNotification(_buildMode, "Started");
... create some needed objects
token.Register(TearDown);
InitializeInboxWatcherProcess(...);
}
private void TearDown()
{
_inboxWatcher.Terminate();
_mailman.SendServiceStatusNotification(_buildMode, "Stopped");
}
private void InitializeInboxWatcherProcess(...)
{
// pre create and initiate stuff
_inboxWatcher = new LocalFileSystemWatcherWrapper(...);
_inboxWatcher.Initiate();
}
public class LocalFileSystemWatcherWrapper : IFileSystemWatcherWrapper
{
// do FileSystemWatcher setup and control stuff
}
这很可能是因为您没有取消方法,或者在您调用 Cancel()
时 DoWork()
中的子进程仍然 运行。正如@Damien_The_Unbeliever所说,取消是一项合作任务。
当你调用_cancelTokenSource.Cancel()
时,如果你还没有注册一个回调函数,所有发生的事情就是一个布尔值isCancellationRequested
被设置为true,然后DoWork()
方法负责看到这一点并自行停止执行。但是,这里有一个缺陷,您可能会说,如果调用 Cancel()
时 DoWork()
任务中有一个耗时的循环 运行,则该循环将必须完成在它可以检查 isCancellationRequested
的值之前的迭代,这可能导致挂起。
解决方法是在 DoWork()
方法中插入取消回调函数,参见 here 然后将它们注册到令牌中,这样当您调用 Cancel()
方法时,后台的所有任务 运行 都已停止,无需等待它们。
希望对您有所帮助!