我怎样才能让`计谋......`工作与`产量return`(即一个迭代方法中)? [英] How can I make `await …` work with `yield return` (i.e. inside an iterator method)?

查看:208
本文介绍了我怎样才能让`计谋......`工作与`产量return`(即一个迭代方法中)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有现有的code,类似于:

I have existing code that looks similar to:

IEnumerable<SomeClass> GetStuff()
{
    using (SqlConnection conn = new SqlConnection(connectionString))
    using (SqlCommand cmd = new SqlCommand(sql, conn)
    {
        conn.Open();
        SqlDataReader reader = cmd.ExecuteReader();
        while (reader.Read())
        {
            SomeClass someClass = f(reader); // create instance based on returned row
            yield return someClass;
        }
    } 
}

我似乎可以通过使用受益 reader.ReadAsync()。但是,如果我只是修改了一行:

It seems I could benefit by using reader.ReadAsync(). However, if I just modify the one line:

        while (await reader.ReadAsync())

编译器告诉我,等待只能在标有方法异步使用,并建议我修改方法签名是:

the compiler informs me that await can only be used in methods marked with async, and suggests I modify the method signature to be:

async Task<IEnumerable<SomeClass>> GetStuff()

然而,这样做使得 GetStuff()不可用,因为:

的GetStuff()身体不能是迭代器块,因为任务&LT; IEnumerable的&LT; SomeClass的&GT;&GT; 不是一个迭代器接口类型。

The body of GetStuff() cannot be an iterator block because Task<IEnumerable<SomeClass>> is not an iterator interface type.

我敢肯定,我缺少的异步编程模型的一个重要概念。

I'm sure I am missing a key concept with the async programming model.

问题:

  • 我可以使用 ReadAsync()在我的迭代器?怎么样?
  • 如何看待异步模式不同,因此,我理解它是如何工作在这种情况?
  • Can I use ReadAsync() in my iterator? How?
  • How can I think about the async paradigm differently so that I understand how it works in this type of situation?

推荐答案

现在的问题是你问实际上并没有太大的意义。 的IEnumerable&LT; T&GT; 是一个同步接口,并返回任务&LT; IEnumerable的&LT; T&GT;&GT; 不会帮你多少,因为一些线程将不得不阻塞等待每一个项目,不管是什么。

The problem is what you're asking doesn't actually make much sense. IEnumerable<T> is a synchronous interface, and returning Task<IEnumerable<T>> isn't going to help you much, because some thread would have to block waiting for each item, no matter what.

你真的想回到的是一些异步替代的IEnumerable&LT; T&GT; :像的IObservable&LT; T&GT; ,从TPL数据流或 IAsyncEnumerable&LT数据流块; T&GT;

What you actually want to return is some asynchronous alternative to IEnumerable<T>: something like IObservable<T>, dataflow block from TPL Dataflow or IAsyncEnumerable<T>.

使用TPL数据流,要做到这一点的一种方法是:

Using TPL Dataflow, one way to do this would be:

ISourceBlock<SomeClass> GetStuff() {
    var block = new BufferBlock<SomeClass>();

    Task.Run(async () =>
    {
        using (SqlConnection conn = new SqlConnection(connectionString))
        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            await conn.OpenAsync();
            SqlDataReader reader = await cmd.ExecuteReaderAsync();
            while (await reader.ReadAsync())
            {
                SomeClass someClass;
                // Create an instance of SomeClass based on row returned.
                block.Post(someClass);
            }
            block.Complete();
        } 
    });

    return block;
}

您可能会需要添加错误处理上述code,但除此之外,它应该工作,这将是完全异步的。

You'll probably want to add error handling to the above code, but otherwise, it should work and it will be completely asynchronous.

你的code其余部分将随后使用来自返回块中的项目也以异步方式,可能使用 ActionBlock

The rest of your code would then consume items from the returned block also asynchronously, probably using ActionBlock.

这篇关于我怎样才能让`计谋......`工作与`产量return`(即一个迭代方法中)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆