【问题标题】:Intermediate results in the new Async/Await commands新 Async/Await 命令的中间结果
【发布时间】:2012-05-19 22:49:51
【问题描述】:

我一直在想……

新的 Async 结构是否真的允许中间结果而不需要在消费者端编写新代码?

让我用一个例子来详细说明。

假设我们有一个方法可以将数据下载到字节数组或流中,以更好者为准。

是否有可能,awaits 所说的方法可以在下载完成之前使用内置的异步功能开始消耗字节数组或流?我可以做的是每次下载流的某个部分时引发事件,但这会再次增加混乱。

考虑到awaited 方法返回这样的结果,让我编写一个我(会)期望产生中间结果的代码示例(从我的脑海中,不会是正确的代码!)。

io.Stream data = await downloadData();
byte[4096] buffer = new byte[4096];
while (!data.EOF) {
  (await?) data.Read(buffer, offset, 4096);
}

截至目前,Stream.Read可等待的,但是我们有什么方法可以做到这一点吗?我希望能够通过转账await。我在监督什么吗?

【问题讨论】:

    标签: c# asynchronous async-await .net-4.5 c#-5.0


    【解决方案1】:

    我对它不太熟悉,无法给你一个很好的例子,但因为听起来你不想要一次性结果,而是想要多个结果,这听起来更适合 observable。 Thenter link description hereis 来自 Rx 团队的 2.0 beta 博客文章的图片在这些方面非常有用(恕我直言)。

    【讨论】:

    • OnNext?现在我无法决定!两个答案都适用于不同的场景:D
    【解决方案2】:

    如果您在 .Net 4.5 中使用 Stream,则可以为此使用其 ReadAsync() 方法:

    Stream stream = await downloadData();
    byte[4096] buffer = new byte[4096];
    int read;
    do
    {
        read = await stream.ReadAsync(buffer, 0, buffer.Length);
        // do something with buffer here
    } while (read > 0);
    

    如果您的意思是您的流没有诸如ReadAsync() 之类的方法,但确实支持使用BeginXxx()EndXxx() 模式的异步,并且您想使用await,那么您也可以这样做:

    do
    {
        read = await Task.Factory.FromAsync<byte[], int, int, int>(
            stream.BeginRead, stream.EndRead, buffer, 0, buffer.Length, null);
        // do something with buffer here
    } while (read > 0);
    

    但是,如果您只有一个同步的Read() 方法,那么将它与async 一起使用的唯一方法是在后台线程上启动一个新的Task

    do
    {
        read = await Task.Run(() => stream.Read(buffer, 0, buffer.Length));
        // do something with buffer here
    } while (read > 0);
    

    这段代码的问题是它仍然阻塞了一个线程,这是async 试图避免的。但如果该方法在 GUI 线程上运行,并且您不能在后台线程上运行整个循环,它可能仍然有用。

    【讨论】:

    • +1:Task&lt;T&gt; 无法返回部分结果。解决方案是只要求结果的一部分,例如.Read()Task&lt;T&gt; 可以完全满足。
    • 到目前为止太棒了,虽然 ONE Task 的部分结果没有令人敬畏的模式,但我很难过。所以我们需要创建 HttpWebRequests,获取流并执行 Request.GetResponseAsync 并在结果流上使用您的第一个模式。它仍然比必须运行其中一个回调或 Thread 更好:D
    • @sinni800,我不知道如何从Task&lt;T&gt; 获得部分结果会更好。我觉得这样界面更简单,更容易理解。
    • @svick 我明白你的意思。也许团队已经考虑过,但因此而放弃了它?
    • @svick - 似乎如果你想要这样的“部分结果”,那么你更多的是寻找一个可观察的而不是任务,它是一次性的结果,应该得到流成为每 X 个字节(1KB 或其他)“触发”一次的可观察对象?我是 Rx n00b,所以不确定这是否有意义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-10
    相关资源
    最近更新 更多