【发布时间】:2019-04-15 11:39:39
【问题描述】:
在 C# 控制台应用程序中,我有一个带有几个异步方法的 repo 类:
public class SomeRepo
{
internal Task<IList<Foo>> GetAllFooAsync()
{
// this is actually fake-async due to legacy code.
var result = SomeSyncMethod();
return Task.FromResult(result);
}
public Task<IList<Foo>> GetFilteredFooAsync()
{
var allFoos = await GetAllFooAsync().ConfigureAwait(false);
return allFoos.Where(x => x.IsFiltered);
}
}
在Program.cs:
var someRepo = new SomeRepo();
var filteredFoos = someRepo.GetFilteredFooAsync(); // no await
// a couple of additional async calls (to other classes) without await..
// .. followed by:
await Task.WhenAll(filteredFoos, otherTask, anotherTask).ConfigureAwait(false);
让我莫名其妙的是,如果我在Program.cs 的第 2 行设置一个断点,对someRepo.GetFilteredFooAsync() 的调用不会继续到下一行,而是会一直卡住,直到操作完成(好像它是同步的)。而如果我将调用更改为 GetAllFooAsync(在 GetFilteredFooAsync 中)以包裹在 Task.Run 中:
public class SomeRepo
{
internal Task<IList<Foo>> GetAllFooAsync() { // ... }
public Task<IList<Foo>> GetFilteredFooAsync()
{
var allFoos = await Task.Run(() => GetAllFooAsync).ConfigureAwait(false);
return allFoos.Where(x => x.IsFiltered);
}
}
.. 操作以这种方式按预期工作。是不是因为GetAllFooAsync其实是同步的,而是模仿了一个异步的工作流?
编辑:改写标题并添加 GetAllFooAsync 的内部结构,因为我意识到它们可能是问题的罪魁祸首。
【问题讨论】:
-
在控制台应用程序中 SynchronizationContext 返回线程池。在 ASP.NET 和 Win Forms 中 - 它是同一个线程。这不再是 .NET 核心的情况,但对于 .NET 框架,您必须关心
-
我认为您需要在
GetAllFooAsync中进行 async/await - 同步操作在此方法中。return await Task.FromResult(result);
标签: c# .net async-await task-parallel-library