Асинхронный вызов метода во время выполнения

Я загружаю некоторые сборки во время выполнения и вызываю методы для них, используя Reflections (MethodInfo.Invoke).

Теперь я хочу сделать эти вызовы асинхронными. Поэтому я думаю об использовании Delegate.BeginInvoke(). Но я не уверен, как создать экземпляр делегата, указав имя функции во время выполнения. (У всех примеров, которые я вижу, цель экземпляра делегата разрешается во время самой компиляции.) У меня есть объект MethodInfo, содержащий метод, который нужно вызвать. Есть ли способ сделать это?

   public void Invocation(Object[] inputObjs)
    {
        public delegate string DelegateMethodInfo(int num);

        Assembly assm = Assembly.Load(assemblyName);
        Type type = assm.GetType(className);
        Type[] ctorParams = new Type[0];
        Object[] objs = new Object[0];

        ConstructorInfo ctorInf = type.GetConstructor(ctorParams);
        Object classObj = ctorInf.Invoke(objs);
        MethodInfo methodInf = type.GetMethod(methodName);

        // Need asynchronous invocation.
        //Object retObj = methodInf.Invoke(classObj, inputObjs);

        DelegateMethodInfo del = new DelegateMethodInfo(???); // How to instantiate the delegate???
        del.BeginInvoke((int)inputObjs[0], null, null);
    }

4 ответа

Решение

Просто используйте лямбда-выражение, которое оборачивает вызов methodInf.Invoke. Полученный делегат имеет тип DelegateMethodInfo,

Ты можешь использовать Delegate.CreateDelegate - но вам нужно знать подпись, чтобы у вас был соответствующий тип делегата для создания. Это немного сложно, когда вы в основном только что получили MethodInfo:(Еще хуже, нет эквивалента Delegate.DynamicInvoke для асинхронного выполнения.

Если честно, проще всего было бы запустить новое задание пула потоков, которое вызвало метод:

ThreadPool.QueueUserWorkItem(delegate { methodInf.Invoke(classObj, inputObjs);});

Это похоже на другие ответы, но вы можете создать новый Func и назначить methodInf.Invoke метод к этому. Вот пример

class Other
{
    public void Stuff()
    { Console.WriteLine("stuff"); }
}

static void Main(string[] args)
{
    var constructor = typeof(Other).GetConstructor(new Type[0]);
    var obj = constructor.Invoke(null);

    var method = typeof(Other).GetMethods().First();
    Func<object, object[], object> delegate = method.Invoke;
    delegate.BeginInvoke(obj, null, null, null);

    Console.ReadLine();
}

Что он делает, это создает новую переменную типа Func<object, object[], object>, что соответствует подписи MethodInfo.Invoke, Затем он получает ссылку на фактический метод invoke вашего объекта и вставляет эту ссылку в переменную.

Так как Func<> тип делегата, вы можете использовать BeginInvoke

Вы смотрели на использование MethodInvoker (делегата, а не класса) и не пытались создать дополнительного делегата? Используя анонимный метод с этим, вы можете получить то, что вам нужно. Или я могу курить крэк. Но, по сути, MethodInvoker действует как стандартный делегат без параметров, а затем в методе anon вы передаете свои параметры анонимному коду MethodInvoker. Я использовал его в WinForms для создания Form.BeginInvoke без необходимости создавать делегатов слева и справа. Если нужно, и вы можете подождать, ответьте мне, и я передам вам образец кода сегодня вечером (я на западном побережье США... GMT -8).

Другие вопросы по тегам