我搜索过StackOverflow并没有找到对我特定情况的明确答案。 我有一个方法:
public async Task InitializeMachine()
{
await DoSomeWork1();
// other stuff
await DoSomeWork2();
// other stuff
}
请注意,它返回的签名是Task
,而不是Task<T>
。很难(如果不是不可能的话)重写这样的所有方法。
我想从同步方法调用此方法并让它等待InitializeMachine方法完全完成。同样,很难将其更改为异步方法(我将在下面为感兴趣的人描述原因)。
我查看了一些相关的问题和参考资料,例如:
https://msdn.microsoft.com/en-us/magazine/mt238404.aspx 和
await works but calling task.Result hangs/deadlocks 和
How to call asynchronous method from synchronous method in C#?
答案看起来很旧(也许还有更好的方法?)至少在很多情况下,它们似乎依赖于返回Task<T>
的异步方法,而不仅仅是Task
。
我有
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"
}
有人可以告诉我应该使用哪种方法以及为什么?正如我所说,我试图进行研究,但发现自己在所有争论中都有点迷失,为什么会出现潜在的僵局和其他问题。令我困惑的是所有的分歧。当然到2018年还有一种明确的方式吗?
谢谢,戴夫
P.S。对于那些关心的人,我正在玩SMC状态机库。请参阅:https://sourceforge.net/projects/smc/简而言之,状态机代码是从文本文件自动生成的。但生成的代码是同步方法。是的,我可以破解生成的代码(但它会被覆盖)或重新考虑整个问题(也许InitializeMachine应该不是asynch),但我的问题仍然存在。在我看来,有时同步方法需要调用异步方法,它们应该等到异步方法完成!
答案 0 :(得分:2)
你应该使用这个:
InitializeMachine().GetAwaiter().GetResult();
这将确保InitializeMachine
处引发的任何异常都不会包含在AggregateException
中。请注意,由于您没有返回任何内容(return
方法),因此不需要void
语句。
修改强>
由于您使用的是WPF,如果您只保留异步 - 完全向下的模式会更好:
public async void InitializeMachineAsync()
{
await DoSomeWork1().ConfigureAwait(false);
await DoSomeWork2().ConfigureAwait(false);
}
InitializeMachineAsync
可以是任何事件(例如Window_Load
)
答案 1 :(得分:-1)
最简单的事情是
InitializeMachine().Wait();
有一些关于异常处理的注意事项