[英]await Task doesn't work with IEnumerable
我正在尝试异步执行现有的同步方法,但是,如果该方法是IEnumerable
,那么它似乎会跳过该方法。
这是我要实现的目标的简化版本。
public partial class MainWindow : Window
{
private IEnumerable<int> _Result;
public MainWindow()
{
InitializeComponent();
DoSomethingAmazing();
}
private async void DoSomethingAmazing()
{
_Result = await DoSomethingAsync();
}
private IEnumerable<int> DoSomething()
{
Debug.WriteLine("Doing something.");
//Do something crazy and yield return something useful.
yield return 10;
}
private async Task<IEnumerable<int>> DoSomethingAsync()
{
//Perform the DoSomething method asynchronously.
return await Task.Run(() => DoSomething());
}
}
本质上,创建MainWindow
时,它将触发异步方法来填充_Result
字段。
现在, DoSomething
从未真正执行过。 调试消息永远不会出现。
如果我将IEnumerable
更改为List
,那么一切都很好。 该方法被执行,结果被填充。
我想使用IEnumerable
主要原因是因为我想利用yield return
,它并不是完全必要,但主要只是一个首选项。 我遇到了这个问题,从那以后我一直在挠头。
运行DoSomething
方法的结果是一个实现IEnumerable<int>
的类,并在枚举它时运行您的代码。 您的问题与使用异步无关。 如果运行以下代码
var result = DoSomething();
Debug.WriteLine("After running DoSomething");
var resultAsList = result.ToList();
Debug.WriteLine("After enumerating result");
您将获得此输出。
运行DoSomething之后
做某事。
枚举结果后
现在,DoSomething从未真正执行过。 调试消息永远不会出现。
这是因为当您使用yield return
,编译器将生成一个为您实现IEnumerable<T>
的类,并返回迭代器。 看起来像这样:
Program.<DoSomething>d__3 expr_07 = new Program.<DoSomething>d__3(-2);
expr_07.<>4__this = this;
return expr_07;
其中<DoSomething>d__3
是编译器生成的类,实现IEnumerable<int>
。
现在,由于迭代器使用了延迟执行,因此除非您明确地进行了迭代,否则它不会开始执行。
如果我将IEnumerable更改为List,那么一切都很好。 该方法被执行,结果被填充。
这是因为当您使用List
,您正在实现迭代器,从而有效地使其执行。 这就是为什么您会看到调试消息的原因。
更改您的DoSomethingAmazing方法,它将起作用。
private async void DoSomethingAmazing()
{
_Result = await DoSomethingAsync();
foreach (var item in _Result)
{
Debug.WriteLine(item);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.