Rebus,从异步处理程序创建 AppDomain/实例时出现异常 [英] Rebus, exception when creating AppDomain / Instance from async Handler

查看:32
本文介绍了Rebus,从异步处理程序创建 AppDomain/实例时出现异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们对旧版本不存在的新(异步)版本的 Rebus 存在问题.

We have a problem with the new (async) version of Rebus that didn’t exist with the older version.

在处理 rebus 消息并尝试创建 AppDomain 和 Instance 以动态运行插件代码时,它总是给我一个异常.为了让例子尽可能简单,我做了一个测试方法:

When handling rebus message and trying to create AppDomain and Instance to run plugin code dynamically, it always give me an exception. To make the example as simple as possible, I made a Test method:

public static void Test()
{
    AppDomain ad = AppDomain.CreateDomain("Test");
    Loader loader = (Loader)ad.CreateInstanceAndUnwrap(typeof(Loader).Assembly.FullName, typeof(Loader).FullName);
}

class Loader : MarshalByRefObject
{
}

当我从普通"代码调用该方法时,它可以工作,但是当我从(异步)Rebus 消息处理方法调用它时,它给出了一个异常:

When I’m calling the method from ‘normal’ code it works but when I’m calling it from (async) Rebus message Handle method, it gives an exception:

System.Runtime.Serialization.SerializationException 被捕获
HResult=-2146233076 消息=类型程序集Rebus"中的Rebus.Transport.DefaultTransactionContext",Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 未标记作为可序列化.源 = mscorlib 堆栈跟踪:在 System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName)在 App.Bus.MessageParse.Process.Test() 在 d:\Project\App.Bus.MessageParser\Process.cs:line 45在 App.Bus.MessageParse.Process.d__0.MoveNext() 在 d:\Project\App.Bus.MessageParser\Process.cs:line 28 InnerException:

System.Runtime.Serialization.SerializationException was caught
HResult=-2146233076 Message=Type 'Rebus.Transport.DefaultTransactionContext' in assembly 'Rebus, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable. Source=mscorlib StackTrace: at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName) at App.Bus.MessageParse.Process.Test() in d:\Project\App.Bus.MessageParser\Process.cs:line 45 at App.Bus.MessageParse.Process.d__0.MoveNext() in d:\Project\App.Bus.MessageParser\Process.cs:line 28 InnerException:

对这个问题有什么想法吗?

Any idea about the problem?

推荐答案

Rebus 将其事务上下文存储在 AmbientTransactionContext.Current 中,该上下文由线程的逻辑调用上下文支持,当线程的逻辑调用上下文时,它会自动流向延续你等待某事.

Rebus stores its transaction context in AmbientTransactionContext.Current, which is backed by the thread's logical call context, which automatically flows to continuations when you await something.

它也流向创建的应用程序域,显然;)

It flows to created appdomains as well, apparently ;)

可以将 DefaultTransactionContext 标记为可序列化,但我担心您会得到一个异常,告诉您事务上下文字典中的项目不可序列化.

I could mark the DefaultTransactionContext as serializable, but I fear that you would then just get an exception telling you that the items in the transaction context's dictionary are not serializable.

我无法使事务上下文真正可序列化并保证它可以工作,因此 - 如果您需要在消息处理程序中创建一个应用程序域 - 我建议您暂时删除环境事务上下文 - 只记得把它又回来了:)

There is no way I can make the transaction context truly serializable and guarantee that it would work, so - if you need to create an appdomain in a message handler - I suggest you temporarily remove the ambient transaction context - just remember to put it back again :)

类似以下的内容应该可以解决问题:

Something like the following should do the trick:

public async Task Handle(SomeMessage message)
{
    var transactionContext = AmbientTransactionContext.Current;
    AmbientTransactionContext.Current = null;
    try
    {
        JuggleWithAppDomainsInHere();
    }
    finally
    {
        AmbientTransactionContext.Current = transactionContext;
    }
}

如果您的应用程序中使用 appdomains 进行操作是一种常见模式,我建议您将removing-and-restoring-of-the-ambient-Rebus-transaction"包装在 IDisposable 中,所以你可以

If it's a common pattern in your app that you do stuff with appdomains, I suggest you wrap the "removing-and-restoring-of-the-ambient-Rebus-transaction" in something IDisposable, so you can

using(new DismantleAmbientRebusStuff())
{
    JuggleWithAppDomainsInHere();
}

这篇关于Rebus,从异步处理程序创建 AppDomain/实例时出现异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆