Reputation: 4783
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
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
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
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
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