等待任务不适用于 IEnumerable
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
,这不完全是一个要求,但它主要只是一个偏好。我遇到了这个问题,从那以后我一直在摸不着头脑。
更改您的 DoSomethingAmazing 方法,它将起作用。
private async void DoSomethingAmazing()
{
_Result = await DoSomethingAsync();
foreach (var item in _Result)
{
Debug.WriteLine(item);
}
}
运行使用 DoSomething
方法的结果是一个 class,它实现了 IEnumerable<int>
并且在您枚举代码时将 运行 您的代码。您的问题与使用异步无关。如果你运行下面的代码
var result = DoSomething();
Debug.WriteLine("After running DoSomething");
var resultAsList = result.ToList();
Debug.WriteLine("After enumerating result");
你会得到这个输出。
After running DoSomething
Doing something.
After enumerating result
Now DoSomething never actually executes. The debug message never
appears.
那是因为当你使用yield return
时,编译器会生成一个class为你实现IEnumerable<T>
,return是迭代器。它看起来像这样:
Program.<DoSomething>d__3 expr_07 = new Program.<DoSomething>d__3(-2);
expr_07.<>4__this = this;
return expr_07;
其中 <DoSomething>d__3
是编译器生成的 class,实现 IEnumerable<int>
.
现在,因为迭代器使用延迟执行,它不会开始执行,除非您显式迭代它,而您并没有这样做。
If I change IEnumerable to List, then all is well. The method gets
executed and the result gets populated.
那是因为当您使用 List
时,您正在具体化迭代器,有效地使其执行。这就是您看到出现调试消息的原因。
我正在尝试异步执行现有的同步方法,但是如果该方法是 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
,这不完全是一个要求,但它主要只是一个偏好。我遇到了这个问题,从那以后我一直在摸不着头脑。
更改您的 DoSomethingAmazing 方法,它将起作用。
private async void DoSomethingAmazing()
{
_Result = await DoSomethingAsync();
foreach (var item in _Result)
{
Debug.WriteLine(item);
}
}
运行使用 DoSomething
方法的结果是一个 class,它实现了 IEnumerable<int>
并且在您枚举代码时将 运行 您的代码。您的问题与使用异步无关。如果你运行下面的代码
var result = DoSomething();
Debug.WriteLine("After running DoSomething");
var resultAsList = result.ToList();
Debug.WriteLine("After enumerating result");
你会得到这个输出。
After running DoSomething
Doing something.
After enumerating result
Now DoSomething never actually executes. The debug message never appears.
那是因为当你使用yield return
时,编译器会生成一个class为你实现IEnumerable<T>
,return是迭代器。它看起来像这样:
Program.<DoSomething>d__3 expr_07 = new Program.<DoSomething>d__3(-2);
expr_07.<>4__this = this;
return expr_07;
其中 <DoSomething>d__3
是编译器生成的 class,实现 IEnumerable<int>
.
现在,因为迭代器使用延迟执行,它不会开始执行,除非您显式迭代它,而您并没有这样做。
If I change IEnumerable to List, then all is well. The method gets executed and the result gets populated.
那是因为当您使用 List
时,您正在具体化迭代器,有效地使其执行。这就是您看到出现调试消息的原因。