IRegisteredObject и процесс аварийно завершены из-за незапланированного исключения

1

Прежде всего, я использую ASP.NET 4.0. Затем я обернул IRegisteredObject внутри BackgroundWorker соответствующим блоком try/catch.

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 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()
Теги:
async-await
task-parallel-library

1 ответ

2
Лучший ответ

Ну, вы начинаете выполнять свою Task внутри DoWork используя Task.Factory.Startnew, но затем DoWork завершает выполнение, поскольку он не ожидает использования await или не обрабатывает никаких исключений с использованием продолжения, что означает catch (AggregateException e) довольно бесполезно.

Вы должны зарегистрировать продолжение, используя ContinueWith:

public void DoWork(Action action)
{
     _task = Task.Factory.StartNew(action).ContinueWith((previousTask) => 
       {
           foreach (var innerEx in ex.InnerExceptions)
           {
                Logger.Log(innerEx);
           }
        }, TaskContinuationOptions.OnlyOnFaulted);
}
  • 0
    async / await не следует использовать в ASP.NET 4.0, но ваше второе решение хорошо.
  • 0
    @StephanCleary Я искал использование async-await ASP.NET 4, не могли бы вы подробнее рассказать, почему его не следует использовать? Это из-за маршалинга контекста запроса с LegacyAspNetSynchronizationContext ?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню