Reputation: 8631
I have searched StackOverflow and not found a definitive answer to my particular situation. I have a method:
public async Task InitializeMachine()
{
await DoSomeWork1();
// other stuff
await DoSomeWork2();
// other stuff
}
Notice the signature it returns is Task
, not Task<T>
. It would be difficult (if not impossible to rewrite all the methods like this.
I would like to call this method from a synchronous method AND have it wait for the InitializeMachine method to completely finish. Again, it would be hard to change it into an async method (I'll describe why below for those interested).
I have looked at some related questions and references such as:
https://msdn.microsoft.com/en-us/magazine/mt238404.aspx and
await works but calling task.Result hangs/deadlocks and
How to call asynchronous method from synchronous method in C#?
The answers seem to be old (perhaps there is a newer better way?) and at least in many cases, they seem to depend on the async method returning Task<T>
, not just Task
.
I have
void Initialize()
{
//InitializeMachine(); // Perfectly legal, but will return at first await
//return Task.Run(() => InitializeMachine()).GetAwaiter().GetResult(); // can't get this to compile. My typo? Or because it's Task not Task<T> ? This is the "Thread Pool Hack" in first reference above by Stephen Cleary
var task = Task.Run(() => InitializeMachine()); // these 2 lines work!
task.Wait(); // but see heated argument in 2nd reference in the answer by Herman Schoenfeld. Is it safe?
Task task = Task.Run(async () => await InitializeMachine()); // also works. Comes from 3rd reference by author "Tohid"
}
Can someone tell me which method I should be using and why? As I said, I tried to do the research but found myself a little lost on all the arguments as to why there could be a potential deadlock and other problems. Adding to my confusion was all the disagreements. Surely by 2018 there is a definitive way?
Thanks, Dave
P.S. For those who care, I'm playing with the SMC state machine library. See: https://sourceforge.net/projects/smc/ Briefly, state machine code is automatically generated from a text file. BUT the code generated is synchronous methods. Yes, I could hack the generated code (but it will get overwritten) or rethink the entire problem (perhaps InitializeMachine should be not by asynch), but my question would remain nonetheless. It seems to me there are times where synchronous methods need to call async ones and they should wait until the async method is complete!
Upvotes: 0
Views: 1588
Reputation: 32068
You should be using this:
InitializeMachine().GetAwaiter().GetResult();
This will ensure that any exception raised at InitializeMachine
is not wrapped into an AggregateException
. Note that the return
statement is not needed since you aren't returning anything (void
method).
Edit
Since you are using WPF, it would be better if you just kept the async-all-the-way-down pattern:
public async void InitializeMachineAsync()
{
await DoSomeWork1().ConfigureAwait(false);
await DoSomeWork2().ConfigureAwait(false);
}
InitializeMachineAsync
can be any event (like Window_Load
)
Upvotes: 2
Reputation: 12837
the simplest thing to do is
InitializeMachine().Wait();
there are some considerations around exception handling
Upvotes: -1