我正在尝试异步执行现有的同步方法,但是如果方法是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
,这不是一个要求,但它主要是只是一个偏好。我遇到过这个问题,从那时起我一直在挠头。
答案 0 :(得分:3)
运行IEnumerable<int>
方法的结果是一个实现var result = DoSomething();
Debug.WriteLine("After running DoSomething");
var resultAsList = result.ToList();
Debug.WriteLine("After enumerating result");
的类,并在枚举时运行代码。您的问题与使用异步无关。如果您运行以下代码
animate
你会得到这个输出。
运行DoSomething后
做点什么。
枚举结果后
答案 1 :(得分:2)
现在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
时,你正在实现迭代器,有效地使它执行。这就是您看到调试消息的原因。
答案 2 :(得分:0)
更改您的DoSomethingAmazing方法,它将起作用。
private async void DoSomethingAmazing()
{
_Result = await DoSomethingAsync();
foreach (var item in _Result)
{
Debug.WriteLine(item);
}
}