我浏览了StackOverflow上的其他问题,但其他问题/答案似乎都不符合我的情况:
我已经在一个类中编写了一个async
方法,我需要从派生自。netSystem.Management.Automation.Cmdlet
类的另一个类中的重写方法中调用。
public async Task TestReadingFile()
{
using MyReader reader = new MyReader(SetupMyStream("Contoso.txt"));
await foreach (MyDataObject obj in reader.GetFrames())
{
Debug.Print($"{reader.Progress}: {obj.GetType().Name} - {obj}");
}
}
现在,在我的类的ProcessRecord
覆盖Cmdlet
基类我不能使用async
。但是,当然,我想等待结果。
我该怎么做?
我的期望是使用这样的东西:
protected override void ProcessRecord()
{
using MyReader reader = new MyReader(MyFilePath);
IAsyncEnumerator<MyDataObject> enumerator = reader.GetFrames().GetAsyncEnumerator();
while (enumerator.MoveNextAsync().GetAwaiter().GetResult())
{
MyDataObject obj = enumerator.Current;
Debug.Print($"{reader.Progress}: {obj.GetType().Name} - {obj}");
}
}
但是这种方法会抛出一个InvalidOperationException
。
这是怎么做的正确的方式?
得到InvalidOperationException
的原因是ValueTask
不能像Task
那样同步等待。所以简单的解决办法就是用AsTask()
方法把它变成Task
。
枚举数是一次性的,这意味着您应该在使用后将其丢弃。IEnumerator
继承IDisposable
,IAsyncEnumerator
继承IAsyncDisposable
。在正常情况下,你应该使用await using
,但由于方法是同步的,我们必须自己降低这个东西。首先,将其转换为try-finally
结构,然后同步等待返回的任务。
protected override void ProcessRecord()
{
using MyReader reader = new MyReader(MyFilePath);
IAsyncEnumerator<MyDataObject> enumerator = reader.GetFrames().GetAsyncEnumerator();
try
{
while (enumerator.MoveNextAsync().AsTask().GetAwaiter().GetResult())
{
MyDataObject obj = enumerator.Current;
Debug.Print($"{reader.Progress}: {obj.GetType().Name} - {obj}");
}
}
finally
{
enumerator?.DisposeAsync().AsTask().GetAwaiter().GetResult();
}
}