Можно ли прикрепить к событию AppDomain.UnhandledException? - PullRequest
4 голосов
/ 04 ноября 2010

Я пытаюсь создать AppDomain и присоединить его к событию UnhandledException из F #, и мне не очень повезло.В моем обработчике событий мне нужна ссылка на домен, который вызвал событие, а также на аргументы события.

Чтобы воспроизвести эту проблему, следующий код должен быть запущен в скомпилированном приложении.Запуск его в F # Interactive приводит к другой, возможно, не связанной с ошибкой.

open System
open System.Reflection

let domainError (domain:AppDomain) (args:UnhandledExceptionEventArgs) =
    ()

let domain = AppDomain.CreateDomain("test")
domain.UnhandledException
|> Event.add (domainError domain)

Это компилируется просто отлично, но во время выполнения я получаю следующую ошибку:

SerializationException:Тип 'Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers+h@720' в сборке 'FSharp.Core, версия = 4.0.0.0, Culture = нейтральный, PublicKeyToken = b03f5f7f11d50a3a' не помечен как сериализуемый.

Трассировка стека, сопровождающая эту ошибку, выглядит следующим образом:

at System.AppDomain.add_UnhandledException(UnhandledExceptionEventHandler value)
at Program.clo@9.Invoke(UnhandledExceptionEventHandler eventDelegate) in c:\users\joel\documents\visual studio 2010\Projects\EventTest\Program.fs:line 9
at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.CreateEvent@716.Subscribe(IObserver`1 observer)
at Microsoft.FSharp.Control.CommonExtensions.SubscribeToObservable[T](IObservable`1 x, FSharpFunc`2 callback)
at Microsoft.FSharp.Control.EventModule.Add[T,TDel](FSharpFunc`2 callback, IEvent`2 sourceEvent)
at <StartupCode$EventTest>.$Program.main@() in c:\users\joel\documents\visual studio 2010\Projects\EventTest\Program.fs:line 9

Теперь я, очевидно, не могу сделать сериализуемый Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers+h@720, поэтому кто-нибудь может предложить работоспособный способ присоединения к этому конкретному событию?Спасибо за любые предложения.

Обновление

Благодаря предложению от ChaosPandion эта версия работает:

open System
open System.Reflection

let domainError (sender:obj) (args:UnhandledExceptionEventArgs) =
    let problemDomain = sender :?> AppDomain
    printfn "Unhandled exception in app domain: %s" problemDomain.FriendlyName
    ()

let domain = AppDomain.CreateDomain("test")
domain.UnhandledException.AddHandler(UnhandledExceptionEventHandler(domainError))

1 Ответ

3 голосов
/ 04 ноября 2010

После некоторой дополнительной настройки я обнаружил, что этот пример потерпит неудачу:

let domainError (domain:AppDomain) =
        let handler (sender:obj) (e:UnhandledExceptionEventArgs) = 
            let msg = (e.ExceptionObject :?> Exception).Message
            printfn "An exception was unhandled in %s\nMessage:%s" domain.FriendlyName msg
        new UnhandledExceptionEventHandler(handler)

let main() =
    let domain = AppDomain.CreateDomain("test")
    let handler = domainError domain
    domain.UnhandledException.AddHandler handler

Я взломал Reflector и нашел основную причину. (что на самом деле совершенно очевидно сейчас, когда я об этом думаю.)

internal class handler@28 : OptimizedClosures.FSharpFunc<object, UnhandledExceptionEventArgs, Unit>
{
    // Fields
    public AppDomain domain;

    // Methods
    internal handler@28(AppDomain domain);
    public override Unit Invoke(object sender, UnhandledExceptionEventArgs e);
}

Это в значительной степени означает, что единственный способ заставить это работать - не создавать замыканиедоменный объект.Я не уверен, что это сработает для вас, но вы можете попробовать использовать следующее из обработчика:

AppDomain.CurrentDomain
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...