是否可以附加到AppDomain.UnhandledException事件?

时间:2010-11-04 03:40:01

标签: f#

我正在尝试创建一个AppDomain并从F#附加到它的UnhandledException事件,而且我没有太多运气。在我的事件处理程序中,我需要引用触发事件的域以及事件参数。

要重现此问题,必须在已编译的应用程序中运行以下代码。在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:在程序集'FSharp.Core中键入'Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers+h@720',Version = 4.0.0.0,Culture = neutral,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 个答案:

答案 0 :(得分:3)

经过一些调整后,我发现这个例子会失败:

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