Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 等待IEnumerable项目(等待后再等待)_C#_.net_Linq_Asynchronous_Async Await - Fatal编程技术网

C# 等待IEnumerable项目(等待后再等待)

C# 等待IEnumerable项目(等待后再等待),c#,.net,linq,asynchronous,async-await,C#,.net,Linq,Asynchronous,Async Await,我有一个迭代器-返回类型是IEnumerable,这样我可以在以后等待每个项目: private IEnumerable<Task<Event>> GetEventsAsync(long length) { var pos = _reader.BaseStream.Position; while (_reader.BaseStream.Position - pos < length) { yield return ReadEv

我有一个迭代器-返回类型是
IEnumerable
,这样我可以在以后等待每个项目:

private IEnumerable<Task<Event>> GetEventsAsync(long length)
{
    var pos = _reader.BaseStream.Position;
    while (_reader.BaseStream.Position - pos < length)
    {
        yield return ReadEvent(); // this method is async
    }
}


我不想使用Task.whell,因为它会列举所有的东西,而这正是我试图避免的。我想让这个迭代器在传入构造函数之前保持不变。我想推迟执行。(如果这种方法不可行,我将使用工厂方法)

产量
不符合预期,等待,可能下一个c版本将有更好的规定。现在,您只需等待事件并将其存储在列表中。另外,如果您的
ReadEvent
依赖于
Stream.Position
,则您不能使用
Task.whalll
或任何其他方式,而只需在列表中枚举并存储结果

private async Task<IEnumerable<Event>> GetEventsAsync(long length)
{
    List<Event> events = new List<Event>();
    var pos = _reader.BaseStream.Position;
    while (_reader.BaseStream.Position - pos < length)
    {
        // if ReadEvent depends on _reader.BaseStream.Postion
        // you cannot use Task.WhenAll, because it executes all
        // tasks in parallel, where else, you must await to finish
        // your previous ReadEvent
        Event e = await ReadEvent(); // this method is async
        events.Add(e);
    }
    return events;
}
专用异步任务GetEventsAsync(长)
{
列表事件=新列表();
var pos=_reader.BaseStream.Position;
while(_reader.BaseStream.Position-pos
您可以在所有时候使用
进行此操作,并异步等待

private async Task<EventManager> ReadEventManagerAsync()
{
    // some other stuff
    var length = Reverse(await _reader.ReadInt32()); // bytes to read
    var events = GetEventsAsync(length); // cant await iterator. so use linq
    await Task.WhenAll(events);
    return new EventManager(events.Select(x => x.Result));
}
private异步任务ReadEventManagerAsync()
{
//一些其他的东西
var length=Reverse(等待_reader.ReadInt32());//要读取的字节数
var events=GetEventsAsync(length);//不能等待迭代器。所以使用linq
等待任务。何时(事件);
返回新的EventManager(events.Select(x=>x.Result));
}

不,它将同步运行(构造函数毕竟不能是异步的)

这并不意味着如果你从未真正执行过任务,你的表现就会受到影响
events.Select(async e=>await e)。Select(x=>x.Result)
最终返回一个可枚举项。它不会调用第一个
Select
,这意味着等待的代码永远不会被调用

这段代码会异步运行吗

否。枚举可枚举项时,它将同步运行,并完成

Select(async e=>await e)
什么都不做。这与
Select(e=>e)
相同。它是而不是
等待e

将流转换为-
IEnumerable
的整个过程非常奇怪。也许你想把它转换成
IObservable

如果这种方法不可行,我将使用工厂方法


是的,您不能在构造函数中使用
wait
,阻塞可能会导致死锁。异步工厂方法可能是最好的选择。

如果不在构造函数中枚举此查询,则它将根本不会运行。请显示构造函数代码我理解,我正在构造函数中枚举此查询。我使用了很多自制的方法,所以这并没有真正的帮助。我有这样的东西
UnknownEvents=events.sievent(AEvents.sievent(BEvents.ToReadOnlyCollection)(x=>x)这将枚举所有内容@SergeyBerezovskiyyield不能像预期的那样与Wait一起工作,可能下一个c#版本会有更好的规定。现在,您只需等待事件并将其存储在列表中,看看我的答案。另外,如果您的ReadEvent依赖于
Stream.Position
,则您不能使用
Task.WhenAll
或任何其他方式,而只需将结果枚举并存储在列表中。
Task.WhenAll
将并行执行每个操作,making
Stream.Position
返回无效的位置。所以,如果我在构造函数中枚举这个,它会同步运行吗?然后,我想我别无选择,只能按照@akashkava的建议将结果存储在列表中,并将列表传递给构造函数。将其强制放入列表将使代码已经运行,所以不确定这是否是您想要的@卡泽马卡里耶先生。我想让事情看起来很酷,(并防止额外的列表创建-无论如何GC将处理它顺便说一句),但我认为这就是我现在所能做的,谢谢你的回答,我接受这两个答案,如果我可以:)
await e;
return e.Result; // is it safe?
private async Task<IEnumerable<Event>> GetEventsAsync(long length)
{
    List<Event> events = new List<Event>();
    var pos = _reader.BaseStream.Position;
    while (_reader.BaseStream.Position - pos < length)
    {
        // if ReadEvent depends on _reader.BaseStream.Postion
        // you cannot use Task.WhenAll, because it executes all
        // tasks in parallel, where else, you must await to finish
        // your previous ReadEvent
        Event e = await ReadEvent(); // this method is async
        events.Add(e);
    }
    return events;
}
private async Task<EventManager> ReadEventManagerAsync()
{
    // some other stuff
    var length = Reverse(await _reader.ReadInt32()); // bytes to read
    var events = GetEventsAsync(length); // cant await iterator. so use linq
    await Task.WhenAll(events);
    return new EventManager(events.Select(x => x.Result));
}