Вызов асинхронного метода Cross AppDomain

Из основного AppDomain я пытаюсь вызвать асинхронный метод, определенный в типе, созданном в другом AppDomain.

Например, следующий тип MyClass наследуется от MarshalByRefObject и создается в новом AppDomain:

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

В основном AppDomain я создаю новый AppDomain и создаю экземпляр MyClass внутри этого AppDomain, затем я вызываю асинхронный метод.

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

Конечно, я получаю SerializationException, когда пытаюсь сделать вызов, так как тип Task не наследуется от MarshalByRefObject и не является сериализуемым.

Как я мог обойти это? Мне бы очень хотелось иметь возможность вызывать/ожидать асинхронные методы из типа, созданного в другом AppDomain... Есть ли способ?

Спасибо !


person darkey    schedule 01.03.2013    source источник
comment
Вы можете найти этот вопрос полезным.   -  person Stephen Cleary    schedule 02.03.2013
comment
Это именно то изящное решение, которого я с нетерпением ждал. Спасибо Степан!!!   -  person darkey    schedule 02.03.2013
comment
Решением может быть определение события во втором домене приложения. Первый домен приложения вызывает метод внутри второго, который только запускает событие, управление возвращается к первому домену приложения, а выполнение события продолжается во втором.   -  person Alireza Ahmadi Rad    schedule 28.06.2016


Ответы (1)


Я знаю, что вопросу 7 лет, но на случай, если кто-то найдет это полезным:

В наши дни простым решением может быть вызов синхронного метода с Task.Run и ожидание метода Task.Run.

Скорее, чем:

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

Использовать:

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

Вы можете получить возвращаемое значение метода (если оно не пусто и его возвращаемый тип может пересекать 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 неявно станет Task.Run<returnType>, если делегат имеет непустой возвращаемый тип (сам делегат станет Func, а не Action). Если вы используете скобки для создания лямбда-выражения, вам придется вручную возвращать результат метода, чтобы подразумевать, что это Func, а не Action:

var result = await Task.Run(()=>{ return RemoteObject.GetValue(parameter); });
person Matheus Rocha    schedule 10.09.2020