IIS 7.5应用程序池重启导致方法无法完成

3

我有两种方法:

public void Stop(bool immediate)
{
    Logger.Log(LogLevel.Debug, "Shutdown detected. Immediate: " + immediate);
    Shutdown();
    Logger.Log(LogLevel.Debug, "Unregistering");
    HostingEnvironment.UnregisterObject(this);
}

public void Shutdown()
{
    Logger.Log(LogLevel.Debug, "Preparing to stop UploadQueue");
    IsProcessing = false;

     //Set tasks to cancel to prevent queued tasks from parsing
     _cancellationTokenSource.Cancel();

     Logger.Log(LogLevel.Debug, "Waiting for " + _workerTasks.Count + " tasks to finish or cancel.");
     //Wait for tasks to finish
     Task.WaitAll(_workerTasks.Values.ToArray());

     Logger.Log(LogLevel.Debug, "Stopped UploadQueue");
}

该类使用IRegisteredObject接口来接收关闭通知。在我的日志中,我得到了以下内容:
2014-07-18 15:30:55,913,DEBUG,Shutdown detected. Immediate: False
2014-07-18 15:30:55,913,DEBUG,Preparing to stop UploadQueue
2014-07-18 15:30:55,913,DEBUG,Waiting for 35 tasks to finish or cancel.
...
bunch of stuff
...
2014-07-18 15:31:28,471,DEBUG,Shutdown detected. Immediate: True
2014-07-18 15:31:28,471,DEBUG,Preparing to stop UploadQueue
2014-07-18 15:31:28,471,DEBUG,Waiting for 0 tasks to finish or cancel.
2014-07-18 15:31:28,471,DEBUG,Stopped UploadQueue
2014-07-18 15:31:28,471,DEBUG,Unregistering

第一次为什么没有到达Logger.Log(LogLevel.Debug, "Stopped UploadQueue");?它肯定会取消任务并让正在运行的任务完成。 (任务在运行之前检查是否已取消,否则执行其操作)。


也许在第一种情况下某些任务会抛出异常?因此,Logger.Log()方法不会以这种方式被调用。 - Ilya Luzyanin
1个回答

1

来自Task.WaitAll

聚合异常:

至少有一个任务实例被取消了,或者在至少一个任务实例的执行过程中抛出了异常。如果一个任务被取消了,AggregateException在其InnerExceptions集合中包含一个OperationCanceledException。

您正在通过_cancellationTokenSource.Cancel();取消您的任务,我假设这导致至少有一个任务抛出异常。您可能在更高级别的堆栈框架中捕获它并忽略它。将Task.WaitAll放在try-catch块中:

public void Shutdown()
{
    Logger.Log(LogLevel.Debug, "Preparing to stop UploadQueue");
    IsProcessing = false;

    //Set tasks to cancel to prevent queued tasks from parsing
    _cancellationTokenSource.Cancel();

    Logger.Log(LogLevel.Debug, "Waiting for " + _workerTasks.Count + " tasks to finish or cancel.");

     try
     {
         //Wait for tasks to finish
         Task.WaitAll(_workerTasks.Values.ToArray());

         Logger.Log(LogLevel.Debug, "Stopped UploadQueue");
     }
     catch (AggregationException e)
     {
         // Recover from the exception
     }
}

1
+1 但请注意:从异常中恢复,不要忽略它。 - John Saunders
@JohnSaunders 我总是使用try/catch/swallow,这绝对是最好的。 - Shawn
@Shawn:不,这是最糟糕的。 - John Saunders
@JohnSaunders 讽刺也是最好的。 - Shawn
@Shawn:这是一个国际网站。许多读者可能不知道你在使用讽刺的语气。 - John Saunders
@JohnSaunders 讽刺是一种明显的英式说话方式吗? - Shawn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接