Norgul
Norgul

Reputation: 4783

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?

Upvotes: 0

Views: 3154

Answers (4)

brad
brad

Reputation: 559

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.

Upvotes: 0

Damien_The_Unbeliever
Damien_The_Unbeliever

Reputation: 239804

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();

Upvotes: 1

Suraj Mittal
Suraj Mittal

Reputation: 23

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.

Upvotes: 0

user1562155
user1562155

Reputation:

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.

Upvotes: 0

Related Questions