您将如何实现与Async CTP await
关键字类似的工作?是否有一个简单的实现在所有情况下都像await
一样工作,或者await
是否需要针对不同场景的不同实现?如何在没有Async CTP的情况下实现等待
回答
await
总是涉及同样的转换 - 但这是一个非常痛苦的转变。 库一侧的await
不是太复杂,但棘手的是,编译器为你建立一个状态机,允许继续跳回到正确的位置。
这是可能我的一些hacky使用迭代块(yield return),你可能会伪造类似的东西......但它会非常难看。
我给出了一个DevExpress webinar on what the compiler is doing behind the scenes a few weeks ago - 它显示了来自两个示例的反编译代码,并解释了编译器如何构建一个返回任务,以及“awaiter”必须做什么。它可能对你有用。
您可以在这里找到Jon在youtube上提到的网络研讨会:http://www.youtube.com/watch?v=HpA2x_JvLD4 – ShitalShah 2014-03-14 20:34:29
很少有实现和由迭代器(yield)构成的协程示例。
其中一个例子是Caliburn.Micro框架,它使用此模式进行异步GUI操作。但是对于一般的异步代码,它可以很容易地推广。
的MindTouch DReAM框架实现协同程序上的迭代器模式的顶部是功能上非常相似,异步/等待:
async Task Foo() {
await SomeAsyncCall();
}
与
IYield Result Foo() {
yield return SomeAsyncCall();
}
Result
是梦的版本Task
。框架DLL可以与.NET 2.0+一起工作,但是为了构建它,你需要3.5,因为我们现在使用了很多3.5语法。
新的await
关键字与现有的yield return
关键字具有类似的语义,因为它们都会使编译器为您生成连续样式状态机。所以有可能使用具有与Async CTP相同的行为的迭代器一起破解一些东西。
这是它的样子。
public class Form1 : Form
{
private void Button1_Click(object sender, EventArgs e)
{
AsyncHelper.Invoke<bool>(PerformOperation);
}
private IEnumerable<Task> PerformOperation(TaskCompletionSource<bool> tcs)
{
Button1.Enabled = false;
for (int i = 0; i < 10; i++)
{
textBox1.Text = "Before await " + Thread.CurrentThread.ManagedThreadId.ToString();
yield return SomeOperationAsync(); // Await
textBox1.Text = "After await " + Thread.CurrentThread.ManagedThreadId.ToString();
}
Button2.Enabled = true;
tcs.SetResult(true); // Return true
}
private Task SomeOperationAsync()
{
// Simulate an asynchronous operation.
return Task.Factory.StartNew(() => Thread.Sleep(1000));
}
}
由于yield return
产生IEnumerable
我们的协同程序必须返回一个IEnumerable
。所有的魔法都发生在AsyncHelper.Invoke
方法中。这就是我们的协同程序(伪装成黑客的迭代器)。需要特别注意的是,确保迭代器总是在当前同步上下文中执行(如果存在的话),这在试图模拟await
如何在UI线程上工作时很重要。它通过同步执行第一个MoveNext
,然后使用SynchronizationContext.Send
从工作线程完成其余工作,该工作线程也用于在各个步骤中异步等待。
public static class AsyncHelper
{
public static Task<T> Invoke<T>(Func<TaskCompletionSource<T>, IEnumerable<Task>> method)
{
var context = SynchronizationContext.Current;
var tcs = new TaskCompletionSource<T>();
var steps = method(tcs);
var enumerator = steps.GetEnumerator();
bool more = enumerator.MoveNext();
Task.Factory.StartNew(
() =>
{
while (more)
{
enumerator.Current.Wait();
if (context != null)
{
context.Send(
state =>
{
more = enumerator.MoveNext();
}
, null);
}
else
{
enumerator.MoveNext();
}
}
}).ContinueWith(
(task) =>
{
if (!tcs.Task.IsCompleted)
{
tcs.SetResult(default(T));
}
});
return tcs.Task;
}
}
有关TaskCompletionSource
整个位是我在复制的方式await
可以“回归”的值的尝试。问题是协程有实际返回IEnumerable
,因为它只不过是一个被黑的迭代器。所以我需要想出一个替代机制来捕获返回值。
这有一些明显的局限性,但我希望这给你的一般想法。它还演示了CLR如何使用一个泛化机制来实现协同程序,其中await
和yield return
将以无处不在的方式使用,但以不同的方式提供它们各自的语义。
从我的阅读中,yield return
和await
之间的主要区别是,await
可以明确地返回一个新的值到延续。
SomeValue someValue = await GetMeSomeValue();
而与yield return
,你必须通过引用来完成同样的事情。
var asyncOperationHandle = GetMeSomeValueRequest();
yield return asyncOperationHandle;
var someValue = (SomeValue)asyncOperationHandle.Result;
比尔·瓦格纳从微软写道:an article in MSDN Magazine有关如何使用任务并行库在Visual Studio 2010中实现异步样的行为不会对异步CTP添加依赖。
它采用Task
和Task<T>
广泛里面也有额外的好处,一旦C#5已经出来了,你的代码将做好准备开始使用async
和await
。
- 1. AsyncTask如何在没有deadLock的情况下等待另一个
- 2. CakePHP 3,如何在没有CTP的情况下渲染
- 3. 如何在没有setter的情况下实现INotifyPropertyChanged?
- 4. 我们如何在没有SpingIOC.jar的情况下实现Spring IOC
- 5. 如何在没有等待SimPy的情况下定期生成活动?
- 6. 如何在未等待的情况下轮询未来状态?
- 7. 如何在不等待ssh2的情况下强制加载PHP
- 8. 如何在不等待的情况下调用异步函数?
- 9. 如何在不等待输出的情况下继续CompletableFuture
- 10. 如何在不抛出TaskCanceledExceptions的情况下等待任务?
- 11. 如何在不等待的情况下使用未来?
- 12. 在没有第三方框架的情况下实现DI
- 13. 在没有va_list的情况下实现printf
- 14. 在没有JQuery的情况下实现onclick事件
- 15. 在没有$ _SESSIONs的情况下实现Facebook PHP SDK(3.1.1)
- 16. 在没有XML配置的情况下实现Spring Security Oauth
- 17. 在没有模型的情况下实现MVC架构
- 18. 在没有管理员权限的情况下等待REPORT任务的结束
- 19. 如何在没有SyncAdapter的情况下在Android上实现帐户
- 20. 如何在没有简码的情况下在wordpress中实现FAQ
- 21. 如何在没有插件的情况下在Jquery中实现“观察者”?
- 22. 如何让代码在下面的async/await函数中等待?
- 23. 如何在没有JSX的情况下呈现React.js中的html实体
- 24. 在没有创建实现的情况下实现接口(动态代理?)
- 25. C#如何在没有实现的情况下单元测试接口方法
- 26. 如何在没有内容提供者的情况下实现Loader?
- 27. 如何在没有实现的情况下测试纯虚拟类?
- 28. Java:如何在没有方法调用的情况下实现指针效果?
- 29. 如何使用软件实现在没有GPU的情况下运行CUDA?
- 30. 如何在没有追踪器的情况下制作增强现实
我刚刚发表了一篇关于如何[使用迭代器在C#4中等待任务]的文章(http://www.codeproject.com/Articles/504197/Await-Tasks-in-Csharp4-using-Iterators)。令人惊讶的是,它既不是“哈克”也不是非常丑陋,AFAICT就像等待。一探究竟! – 2012-12-08 21:33:36