IRegisteredObject和进程因未处理的异常而崩溃

时间:2014-08-11 15:05:25

标签: c# asp.net .net task-parallel-library async-await

首先,我使用的是ASP.NET 4.0。接下来,我使用正确的try / catch块将IRegisteredObject包装在BackgroundWorker中。

public class BackgroundWorker
{
    /// <summary>
    /// Runs a background task that is registered with the hosting environment
    /// so it is guaranteed to finish executing.
    /// </summary>
    /// <param name="action">The lambda expression to invoke.</param>
    public static void Run(Action action)
    {
        new IISBackgroundTask().DoWork(action);
    }

    /// <summary>
    /// Generic object for completing tasks in a background thread
    /// when the request doesn't need to wait for the results 
    /// in the response.
    /// </summary>
    class IISBackgroundTask : IRegisteredObject
    {
        /// <summary>
        /// Constructs the object and registers itself with the hosting environment.
        /// </summary>
        public IISBackgroundTask()
        {
            HostingEnvironment.RegisterObject(this);
        }

        /// <summary>
        /// Called by IIS, once with <paramref name="immediate"/> set to false
        /// and then again with <paramref name="immediate"/> set to true.
        /// </summary>
        void IRegisteredObject.Stop(bool immediate)
        {
            if (_task.IsCompleted || _task.IsCanceled || _task.IsFaulted || immediate)
            {
                // Task has completed or was asked to stop immediately, 
                // so tell the hosting environment that all work is done.
                HostingEnvironment.UnregisterObject(this);
            }
        }

        /// <summary>
        /// Invokes the <paramref name="action"/> as a Task.
        /// Any exceptions are logged
        /// </summary>
        /// <param name="action">The lambda expression to invoke.</param>
        public void DoWork(Action action)
        {
            try
            {
                _task = Task.Factory.StartNew(action);
            }
            catch (AggregateException ex)
            {
                // Log exceptions
                foreach (var innerEx in ex.InnerExceptions)
                {
                    Logger.Log(innerEx);
                }
            }
            catch (Exception ex)
            {
                Logger.Log(ex);
            }
        }

        private Task _task;
        private static readonly ILogger Logger = Loggers.Logger.Instance;
    }
}

我称之为,

BackgroundWorker.Run(() => 
         // My Code            
);

但我的asp.net进程有时会崩溃。

Faulting application name: w3wp.exe, version: 7.5.7601.17514, time stamp: 0x4ce7afa2
Faulting module name: KERNELBASE.dll, version: 6.1.7601.17514, time stamp: 0x4ce7c78c
Exception code: 0xe0434352
Fault offset: 0x000000000000a49d
Faulting process id: 0x2b90
Faulting application start time: 0x01cfb515a14c3320
Faulting application path: c:\windows\system32\inetsrv\w3wp.exe
Faulting module path: C:\Windows\system32\KERNELBASE.dll
Report Id: 9f0a3510-2164-11e4-822a-4040610959cf


Application: w3wp.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AggregateException
Stack:
   at System.Threading.Tasks.TaskExceptionHolder.Finalize()

An unhandled exception occurred and the process was terminated.

Application ID: /LM/W3SVC/2/ROOT

Process ID: 11152

Exception: System.AggregateException

Message: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread.

StackTrace:    at System.Threading.Tasks.TaskExceptionHolder.Finalize()

InnerException: System.XXXX

Message: XXXX

StackTrace:   
   at MyMethod
   at System.Threading.Tasks.Task.Execute()

1 个答案:

答案 0 :(得分:2)

好吧,你开始使用TaskDoWorkTask.Factory.Startnew执行DoWork,然后await完成执行,因为没有等待使用catch (AggregateException e)使用延续来处理任何异常,这意味着public void DoWork(Action action) { _task = Task.Factory.StartNew(action).ContinueWith((previousTask) => { foreach (var innerEx in ex.InnerExceptions) { Logger.Log(innerEx); } }, TaskContinuationOptions.OnlyOnFaulted); } 非常无用。

您应该使用ContinueWith注册续集:

{{1}}