2012-03-12 126 views
1

我有一个在C#中开发的Windows服务。在它的Start方法,我有一个初始化如:如何取消任务或立即终止任务执行?

Task _backgroundTask = null; 

CancellationTokenSource _backgroundCancellationSource = null; 

protected override void OnStart(string[] args) 
{ 

...... 

_backgroundCancellationSource = new CancellationTokenSource(); 

CancellationToken token = backgroundCancellationSource.Token; 

_backgroundTask = new Task(() => BackgroundFoldersProcessing(token), token, TaskCreationOptions.LongRunning); 

....... 
} 

现在的方法BackgroundFoldersProcessing看起来是这样的:

void BackgroundFoldersProcessing(CancellationToken token) 
{ 

      while (true) 
      { 
       try 
       { 
        if (token.IsCancellationRequested) 
        {       
         return; 
        } 

        DoSomeWork() 
       } 
       catch (Exception ex) 
       { 
        ......... 
       } 
      } 
} 

现在,停止方法如下:

protected override void OnStop() 
{ 
................. 

_backgroundCancellationSource.Cancel(); 
_backgroundTask.Wait(); 

_backgroundCancellationSource.Dispose(); 
_backgroundTask.Dispose(); 

_backgroundTask = null; 
_backgroundCancellationSource = null; 

................. 
} 

现在问题是当我尝试在处理中途停止服务时,_backgroundTask的Wait方法不会停止服务,直到并且除非BackgroundFold中的DoSomeWork()方法ersProcessing完成后,Windows服务不会停止。

有没有什么办法,虽然我可以停止服务,并且_backgroundTask的执行将被终止,即使DoSomeWork()方法得到完成/执行或没有?我也尝试过BackgroundFoldersProcessing方法中的token.ThrowIfCancellationRequested(),但那也没有奏效。我希望每当我尝试停止服务控制管理器(SCM)的服务时,服务应该立即停止,__backgroundTask应该停止执行BackgroundFoldersProcessing方法并终止。我怎样才能做到这一点?

+0

DoSomeWork()只是花了太长时间?你正在等待它完成。您可能想尝试Wait(TimeSpan)超载并将其设置为三秒。 – 2012-03-12 09:00:09

+0

@NikolaMarkovinović是的,DoSomeWork()需要相当长的时间取决于输入。实际上,我将Package(.zip)文件作为输入。因此,处理一个软件包可能需要几秒到几分钟时间,具体取决于软件包的内容。而且,实际上我尝试了Wait(TimeSpan)以及Wait(int milliSeconds)和其他重载的Wait方法。是的,它的工作。谢谢。 – 2012-03-12 09:57:03

回答

0

您可以尝试使用ThreadAbortException:

限定螺纹:

ThreadStart threadDelegate = new ThreadStart(BackgroundFoldersProcessing); 
Thread thread_ = new Thread(threadDelegate); 
thread_.Start(); 

添加捕捉到BackgroundFoldersProcessing

catch (ThreadAbortException e) 
{ 
    return; 
} 

,当你想关闭它使用:

thread_.Abort(); 
thread_.Join(); 

然后当中止()将被称为ThreadAbortException将被抛出。

+0

这可能是一个很好的方法,它可能在单线程环境中运行良好,但我担心多线程环境中的线程安全问题。假设我将代码移动到一个类中,然后说Work。在Work类中,我可以开发一个方法Start()和Stop(),并在Windows Service的OnStart和OnStop中调用该方法。现在,如果我创建并使用Work类的多个实例,那么您建议的方法是否是线程安全的,并且所有运行的线程是否会异步执行? – 2012-03-12 10:17:39