在尝试更正启动服务时抛出的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 BTW)之后,我无法通过常规方法停止该服务。
这是我遵循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
}
答案 0 :(得分:1)
这很可能是因为您没有取消方法,或者DoWork()
内有子流程在您调用Cancel()
时仍在运行。正如@Damien_The_Unbeliever所说,取消是一项合作任务。
如果您未注册回调函数而调用_cancelTokenSource.Cancel()
时,发生的一切是将布尔值isCancellationRequested
设置为true,则DoWork()
方法负责查看并自行停止执行。但是,您可能会说,这里有一个缺陷,如果在调用DoWork()
时在Cancel()
任务中运行了一个耗时的循环,则该循环必须先完成一次迭代可以检查isCancellationRequested
的值,这可能导致挂起。
解决方法是将取消回调函数插入DoWork()
方法中,请参见here,然后将其注册到令牌中,以便在调用Cancel()
方法时,ALL在后台运行的任务中的一部分无需等待即可停止。
希望这会有所帮助!