简体   繁体   中英

C# wait DLL async method to finish

I have a DLL which has public Task<> method which returns return Task.Factory.StartNew(() => ...) . I am calling it within a program and I want the program to wait for the execution of the task to finish before it continues doing other things. I've added Thread.Sleep(6000) to the DLL to simulate longer execution.

When I'm calling it like this

var invokedTask = myMethod.Invoke(Activator.CreateInstance(myClass), myParams);

It just continues with execution (as expected). But then I tried this:

var invokedTask = Task.Factory.StartNew(() => myMethod.Invoke(Activator.CreateInstance(myClass), myParams));
invokedTask.Wait();

And it doesn't work. How can I make it wait from outside of DLL?

Just Wait for the task that is being returned - don't spin up another Task just to call the original method:

var invokedTask = (Task)myMethod.Invoke(Activator.CreateInstance(myClass), myParams);
invokedTask.Wait();

I think the calling method must have the async keyword in the definition:

async void (or Task) MyCaller()
{
  await Task.Factory.StartNew(() => myMethod.Invoke(Activator.CreateInstance(myClass), myParams));

}

void or Task depends on which context you are in.

When you wait() a Task.Factory.StartNew() the result is a Task Therefore you have to call wait() two times or you can use await operator.

Therefore you can do the following.

var invokedTask = Task.Factory.StartNew(() => myMethod.Invoke(Activator.CreateInstance(myClass), myParams));
var result=await await invokedTask;

Or you can do the following

var invokedTask = Task.Factory.StartNew(() => myMethod.Invoke(Activator.CreateInstance(myClass), myParams));
invokedTask.Wait();
var resultTask=invokedTask.Result;
resultTask.Wait();
var result=resultTask.Result;

However from the question you have posted, it looks like your myMethod.Invoke() returns Task.Factor.StartNew() therefore I would like you to try

var result =await await myMethod.Invoke(Activator.CreateInstance(myClass), myParams);

However it is a bad practice to use Wait() and then Result() as it block the current thread. Therefore I would like you to use await.

This example may help:

public class MagicClass
{
    private int magicBaseValue;

    public MagicClass()
    {
        magicBaseValue = 9;
    }

    public Task<int> ItsMagic(int preMagic)
    {
        return Task.Factory.StartNew(() => preMagic * magicBaseValue);
    }
}

public class TestMethodInfo
{
    public static void Main()
    {
        // Get the ItsMagic method and invoke with a parameter value of 100
        Type magicType = typeof(MagicClass);
        MethodInfo magicMethod = magicType.GetMethod("ItsMagic");
        var magicValue = ((Task<int>)(magicMethod.Invoke(Activator.CreateInstance(typeof(MagicClass)), new object[] { 100 }))).Result;

        Console.WriteLine("MethodInfo.Invoke() Example\n");
        Console.WriteLine("MagicClass.ItsMagic() returned: {0}", magicValue.ToString());

        Console.ReadKey();
    }
}

You can cast your Invoke as a Task<> and then get the Result. This will wait until the method is done executing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM