C#4.0の悲しい頃、IEnumerableの "yield return"継続をハッキングしてオブザーバブルを待つことで、GUIスレッドで非同期ワークフローを可能にする次の "WorkflowExecutor"クラスを作成しました。したがって、次のコードは、button1Clickでテキストを更新する単純なワークフローを開始し、button2をクリックするのを待ち、1秒後にループします。非同期の仕事をするために「利回り」継続を使ってobservableで待っています
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);
}
}
アイデアのスマートな部分、ダニエルエリカーのAsyncIOPipeのアイデアから撮影された:http://smellegantcode.wordpress.com/2008/12/05/asynchronous-sockets-with-yield-return-of-lambdas/、その後、私はそれの上に反応性のフレームワークを追加しました。
これでC#5.0の非同期機能を使用してこれを書き直すのに問題がありましたが、それは簡単なことです。 Observableをタスクに変換すると、それらは1回だけ実行され、whileループは2回目にクラッシュします。どのような助けを借りても大丈夫でしょう。
WorkflowExecutorは非同期/待機メカニズムによって私に与えられていることは何ですか? asyncでできることは何ですか?私はWorkflowExecutorで(同じような量のコードを与えて)できません。
あなたはTask's 'への変換をどのように正確に行うのですか?見た目はどうやってクラッシュするのですか? – svick
そして 'await'はこの種の非同期よりも多くの利点がありますが、大きな違いの1つは待ち時間から戻ることです。例えば。 'string s = client.DownloadStringAsync(url);を待ちます。 – svick