"迭代"在异步方法 [英] "Iterating" over an async method

查看:287
本文介绍了"迭代"在异步方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有关异步CTP的几个相关问题:


  • 我可以遍历迭代器块(一个的IEnumerable< T> 产量返回 T )使用的GetEnumerator()然后枚举的方法的MoveNext()电流()。什么是模拟异步的方法呢?哪有一个非 - 异步调用方法来接收和处理任何等待 ED项目,然后 ContinueWith()?你可以提供一个简短的例子?我只是没有看到它。


  • 此外,在下面的例子中异步方法 MyAwaitable 有一个 GetAwaiter()方法。如果 GetAwaiter()返回字符串,但 THuh 不是字符串,编译器不抱怨。之间有什么类型约束/存在预期 THuh GetAwaiter()

     异步任务< THuh>做一点事()
    {
         VAR X =等待新MyAwaitable(富);     变种Y =等待新MyAwaitable(酒吧);     返回null;
    }


  • 请解释一下C#规范草案的下面一行。是异步任务< T>应该收益 A 默认(T)方法将永远不会被使用?我看到一些样品,似乎没有遵循这个规则 - 返回值似乎可到达的且值为非默认值。这是人迹罕至的价值?如果是这样,为什么无法访问的尴尬return语句?



  

在与返回类型任务℃的异步函数; T> 一些 T
  return语句必须有一个前pression是隐式
  转换为 T ,和身体的终点必须可达。



  • 的规范说所有GetAwaiter,IsCompleted,OnCompleted和调用getResult的意图是不堵? - 这样的话应该在(潜在的)长期运行的操作来定义什么方法

谢谢!


解决方案

  

我想转换延续传递我做(awkardly但成功)与迭代器块和将其转换为异步,而不是使用。我想我的战斗新途径。了解变化的感觉就像撕裂魔术贴相隔3英寸宽的长条。


我能理解你怎么可能有这样的感觉。我劝阻人们试图打造出CPS迭代器块的,因为实在是不适合,不管是什么底层机制迭代器和CPS的共同点。迭代器块的设计感觉良好快速的决策将数据结构为序列或序列转成不同的序列的方法;他们不旨在解决呼叫与电流-延续的普遍问题。

对于这个问题,异步/的await不是precisely呼叫与电流续任,但它涉及了一个数量级更近,效果显着。异步/伺机旨在使基于任务的异步容易;它通过重写code为延续传递风格形式这样做是一个实现细节。

这答案,我在一个相关主题中写道可能有帮助:

<一个href=\"http://stackoverflow.com/questions/4070237/how-could-the-new-async-feature-in-c-sharp-5-0-be-implemented-with-call-cc/4071015#4071015\">How可以在C#5.0的呼叫/立方厘米实施新的异步功能?

我怀疑你遇到的概念性问题是,在迭代式异步的协调器 - 事情搞清楚当迭代器块得到恢复它离开的地方 - 是的的code。你写一些code和你决定何时调用MoveNext的泵迭代器。随着基于任务的异步,code的其他一些大块不适合您。当任务完成时,赔率是好的,它张贴该事实的消息队列某处,然后当消息队列被泵,继续获取与该结果激活。有一个在你的code没有明确的MoveNext的,你可以在点;而,事实上,一个任务已完成,并知道它自己的延续是足以确保继续被放置到用于最终执行的工作队列。

如果您有更多的问题,我建议你张贴在SO和/或异步论坛。

A few related questions about the async CTP:

  • I can iterate over an Iterator Block (an IEnumerable<T> yield-returning T) using GetEnumerator() and then enumerator methods MoveNext(), and Current(). What is the analog for async methods? How can a non-async calling method to receive and process any awaited items and then ContinueWith()? Can you provide a short example? I'm just not seeing it.

  • Also, in this following example async method, MyAwaitable has a GetAwaiter() method. If GetAwaiter() returns a string but THuh is not string, the compiler doesn't complain. What type constraints/expectations exist between THuh and GetAwaiter()?

    async Task<THuh> DoSomething()
    {
         var x = await new MyAwaitable("Foo");
    
         var y = await new MyAwaitable("Bar");
    
         return null;
    } 
    

  • Please explain the following line of the C# spec draft. Are async Task<T> methods supposed to return a default(T) which will never be used? I see some samples that do not seem to follow this rule - the return value seems reachable and the value is non-default. Is this value inaccessible? If so, why the awkward inaccessible return statement?

In an asynchronous function with the return type Task<T> for some T, return statements must have an expression that is implicitly convertible to T, and the endpoint of the body must be unreachable.

  • The spec says "All of GetAwaiter, IsCompleted, OnCompleted and GetResult are intended to be "non-blocking"" - so then in what method should the (potentially) long-running operation be defined?

Thanks!

解决方案

I'm trying to convert continuation-passing I did (awkardly but successfully) with Iterator Blocks and converting it to use async instead. I think I'm fighting the new way. Understanding the change feels like tearing apart 3-inch wide strips of Velcro.

I can understand how you might feel that way. I discourage people from trying to build CPS out of iterator blocks because really it is not a good fit, no matter what underlying mechanisms iterators and CPS have in common. Iterator blocks are designed to feel good for quickly making methods that turn data structures into sequences or turn sequences into different sequences; they're not designed to solve the general problem of call-with-current-continuation.

For that matter, async/await isn't precisely call-with-current-continuation either, though it comes an order of magnitude closer, obviously. Async/await is designed to make task-based asynchrony easier; that it does so by rewriting code into a form of continuation passing style is an implementation detail.

This answer I wrote on a related topic might help:

How could the new async feature in c# 5.0 be implemented with call/cc?

I suspect that the conceptual problem that you're having is that in iterator-style asynchrony, the "orchestrator" -- the thing figuring out when the iterator block gets to resume where it left off -- is your code. You write some code and you decide when to call MoveNext to pump the iterator. With task-based asynchrony, some other hunk of code does that for you. When a task completes, odds are good that it posts that fact to a message queue somewhere, and then when the message queue is pumped, the continuation gets activated with the result. There's no explicit "MoveNext" in your code that you can point at; rather, the fact that a task has completed and knows its own continuation is sufficient to ensure that the continuation is put onto a work queue for eventual execution.

If you've got more questions, I encourage you to post them on SO and/or the async forum.

这篇关于&QUOT;迭代&QUOT;在异步方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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