所以在C# 4.0的不幸日子里,我创建了以下"WorkflowExecutor"类,通过对IEnumerable的"yield return"继续进行黑客攻击,允许在GUI线程中执行异步工作流,等待可观察对象。因此,以下代码将在button1Click时启动一个简单的工作流程,更新文本,等待您单击button2,然后在1秒后循环。
public sealed partial class Form1 : Form {
readonly Subject<Unit> _button2Subject = new Subject<Unit>();
readonly WorkflowExecutor _workflowExecutor = new WorkflowExecutor();
public Form1() {
InitializeComponent();
}
IEnumerable<IObservable<Unit>> CreateAsyncHandler() {
Text = "Initializing";
var scheduler = new ControlScheduler(this);
while (true) {
yield return scheduler.WaitTimer(1000);
Text = "Waiting for Click";
yield return _button2Subject;
Text = "Click Detected!";
yield return scheduler.WaitTimer(1000);
Text = "Restarting";
}
}
void button1_Click(object sender, EventArgs e) {
_workflowExecutor.Run(CreateAsyncHandler());
}
void button2_Click(object sender, EventArgs e) {
_button2Subject.OnNext(Unit.Default);
}
void button3_Click(object sender, EventArgs e) {
_workflowExecutor.Stop();
}
}
public static class TimerHelper {
public static IObservable<Unit> WaitTimer(this IScheduler scheduler, double ms) {
return Observable.Timer(TimeSpan.FromMilliseconds(ms), scheduler).Select(_ => Unit.Default);
}
}
public sealed class WorkflowExecutor {
IEnumerator<IObservable<Unit>> _observables;
IDisposable _subscription;
public void Run(IEnumerable<IObservable<Unit>> actions) {
_observables = (actions ?? new IObservable<Unit>[0]).GetEnumerator();
Continue();
}
void Continue() {
if (_subscription != null) {
_subscription.Dispose();
}
if (_observables.MoveNext()) {
_subscription = _observables.Current.Subscribe(_ => Continue());
}
}
public void Stop() {
Run(null);
}
}
这个想法中的巧妙部分,使用“yield”连续来完成异步工作,是从Daniel Earwicker的AsyncIOPipe想法中借鉴而来:http://smellegantcode.wordpress.com/2008/12/05/asynchronous-sockets-with-yield-return-of-lambdas/,然后我在其之上添加了响应式框架。
现在,我尝试使用C# 5.0中的async特性进行重写,但似乎应该很容易做到。当我将observables转换为tasks时,它们只运行一次,并且while循环第二次会崩溃。任何帮助修复此问题的建议都将不胜感激。
除此以外,async/await机制能给我什么,WorkflowExecutor却不能?是否有任何我可以使用async/await实现而非WorkflowExecutor(代码量相似)的功能?
await
相对于这种异步方式有许多优势,但其中一个重要的区别是从可等待对象返回。例如:string s = await client.DownloadStringAsync(url);
。 - svick