在调用第一个await
之前,在异步方法开始时使用昂贵的代码是不是很糟糕?这段代码应该用TaskEx.Run
代替吗?
public async Task Foo()
{
// Do some initial expensive stuff.
// ...
// First call to an async method with await.
await DoSomethingAsync;
}
答案 0 :(得分:10)
正如里德所说,这实际上取决于背景。代码必须在某些点运行 - 但是根据上下文,它最终可能会在线程池线程上运行而不是某些关键线程。
我使用Task.Run
:
TaskEx.Yield
public async Task Foo()
{
await TaskEx.Yield();
// Do expensive stuff
}
据我所知,这基本上是一种立即返回调用者的方法,但允许其他异步方法直接安排。如果您使用的是Windows窗体UI线程,那么这样做是没有意义的,因为您将立即回到UI线程(并在那里运行昂贵的代码) - 但如果您处于上下文中这将是有意义的不应该阻止当前线程,但是在另一个线程上运行continuation。
答案 1 :(得分:5)
这不一定是坏事,但可能会产生意想不到的后果。如果调用者希望代码完全异步,那么昂贵的代码将同步运行。这将导致它的行为部分类似于同步方法,但也是异步的,这是两个世界中最糟糕的一种(异步的额外复杂性,没有复制性......)
如果可能的话,我建议尝试使用尽可能少的“昂贵”代码导致第一次等待。使用Task.Run
(或CTP中的TaskEx.Run
)来包装昂贵的代码,或者将昂贵的代码移动到它自己的异步方法中(在await
之后)将在这种情况下有益