7

From the main AppDomain, I am trying to call an async method defined in a type instantiated in a different AppDomain.

For example, the following type MyClass inherits from MarshalByRefObject and is instantiated in a new AppDomain :

public class MyClass : MarshalByRefObject
{
  public async Task<string> FooAsync()
  {
     await Task.Delay(1000);
     return "Foo";
  }
}

In the main AppDomain I create a new AppDomain and create an instance of MyClass inside this AppDomain, then I make a call to the async method.

var appDomain = AppDomain.CreateDomain("MyDomain");
var myClass = (MyClass)appDomain.CreateInstanceAndUnwrap(typeof(MyClass).Assembly.FullName, typeof(MyClass).FullName);
await myClass.FooAsync(); // BAM !

Of course, I get a SerializationException when I try to make the call, as the Task type does not inherit from MarshalByRefObject, nor is serializable.

How could I get arround this ? I would really like to be able to call/await on async methods from a type instantiated in another AppDomain ... Is there a way ?

Thanks !

darkey
  • 3,672
  • 3
  • 29
  • 50
  • 3
    You may find [this question](http://stackoverflow.com/questions/15142507/deadlock-when-combining-app-domain-remoting-and-tasks) helpful. – Stephen Cleary Mar 01 '13 at 23:28
  • This is exactly the kind of elegant solution I was looking forward to. Thanks Stephen !!! – darkey Mar 01 '13 at 23:49
  • Defining an event in second appdomain may be a solution. First appdomain calls a method inside the second one that only triggers an event, control comes back to first appdomain and execution of event continues in second one. – Alireza Ahmadi Rad Jun 28 '16 at 15:41

1 Answers1

0

I know the question is 7 years old, but in case anyone finds this helpful:

A simple solution these days could be calling a synchronous method with Task.Run and awaiting the Task.Run method.

Rather than:

await RemoteObject.MethodAsync(); //Still throws a SerializationException.

Use:

await Task.Run(RemoteObject.Method); //If the method has no parameters.
await Task.Run(()=>RemoteObject.Method(parameter)); // If it does.

You can get the method's return value (if it isn't void, and its return type can cross AppDomains):

var result = await Task.Run(RemoteObject.GetDefaultValue); // If the method has no parameters.
var result = await Task.Run(()=>RemoteObject.GetValue(parameter)); // If it does.

Task.Run will implicitly become Task.Run<returnType> when the delegate has a non-void return type (the delegate itself will become a Func rather than an Action). If you use brackets to create a lambda expression, then you'll have to manually return the result of the method in order to imply it is a Func rather than an Action:

var result = await Task.Run(()=>{ return RemoteObject.GetValue(parameter); });
Matheus Rocha
  • 1,152
  • 13
  • 22