从异步处理程序

时间:2015-12-01 12:58:49

标签: c# plugins appdomain rebus

我们遇到了Rebus的新(异步)版本的问题,旧版本不存在。

当处理rebus消息并尝试创建AppDomain和Instance以动态运行插件代码时,它总是给我一个例外。 为了使示例尽可能简单,我制作了一个测试方法:

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消息Handle方法调用它时,它给出了一个例外:

  

发现了System.Runtime.Serialization.SerializationException   HResult = -2146233076消息=类型   汇编'Rebus中的'Rebus.Transport.DefaultTransactionContext',   Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'未标记   可序列化。 Source = mscorlib StackTrace:          在System.AppDomain.CreateInstanceAndUnwrap(String assemblyName,String typeName)          位于d:\ Project \ App.Bus.MessageParser \ Process.cs中的App.Bus.MessageParse.Process.Test():第45行          位于d:\ Project \ App.Bus.MessageParser \ Process.cs中的App.Bus.MessageParse.Process.d__0.MoveNext():第28行InnerException:

关于这个问题的任何想法?

1 个答案:

答案 0 :(得分:2)

Rebus将其事务上下文存储在AmbientTransactionContext.Current中,该事务上下文由线程的逻辑调用上下文支持,当您await时,它会自动流向continuation。

它也流向创建的appdomains,显然;)

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

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

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

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

如果你的应用程序中有一个常见的模式,你用appdomains做了什么,我建议你包装"删除和恢复环境-Rebus-事务"在IDisposable内,您可以

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