モーダルダイアログをシミュレートするようにコードを更新しようとしていますが、Reactive Extensionsはそれを行うのに適切なツールのように感じましたが、機能させることができません。
現在、コードは次のようになっています。
public bool ShowConfirmationDialogs(IEnumerable<ItemType> items)
{
bool canContinue = true;
foreach (var item in items)
{
Dialog dialog = new Dialog();
dialog.Prepare(item); // Prepares a "dialog" specific to each item
IObservable<bool> o = Service.ShowDialog(dialog, result =>
{
// do stuff with result that may impact next iteration, e.g.
canContinue = !result.Condition;
});
// tried using the following line to wait for observable to complete
// but it blocks the UI thread
o.FirstOrDefault();
if (!canContinue)
break;
}
if (!canContinue)
{
// do something that changes current object's state
}
return canContinue;
}
これまで、ラムダ式のコードは、で示される「ダイアログ」ShowDialog
が閉じられたときに処理を行うために使用されていました。の呼び出しShowDialog
は非ブロッキングであり、を返すために使用されvoid
ます。
舞台裏で行われるShowDialog
のは、オブジェクトがObservableCollection
画面に表示されるようにに追加されることです。
ダイアログが閉じられたときにサブスクライバーのwho呼び出しをShowDialog
返すように変更しました。これは機能します。次のコードでテストしました。IObservable<bool>
OnCompleted
o.Subscribe(b => Console.WriteLine(b), () => Console.WriteLine("Completed"));
そして"Completed"
、ダイアログを閉じると文字列が表示されます。私の問題は、上の行が非ブロッキングであるため、いくつかのダイアログを表示できる可能性があることですが、これはやりたくないことです。
私は次のことを試しました:
o.FirstOrDefault();
プログラムは、オブザーバブルが何かを送信するか完了するまでそこで待機すると想定します。プログラムは大丈夫ですが、UIもフリーズします。つまり、ダイアログが表示されないため、閉じることができないため、observableが完了しません。
ObserveOn
を使用していくつかのバリエーションをSubscribeOn
試し、UIスレッドにその作業を任せようとしましたが、運がありませんでした。どんなアイデアでも大歓迎です。私の主な目標は、を使用するときのように、コードをシーケンシャルに見せることWindow.ShowDialog
です。
要約すると:(そしてコメントでクリスに答える)
問題は、ShowDialog
非ブロッキングであり、前述のように、期待される動作はを使用した場合と同じであるということWindow.ShowDialog
です。現在、ブロックすることはできませんが、ループが続行され、いくつかのダイアログが表示されます。または、(を使用してFirstOrDefault
)ブロックすることもできますが、UIもブロックされるため、オブザーバブルを完了するためにダイアログを閉じることができません。
より多くの説明:(謎めきのために)
呼び出すとShowDialog
、モーダルのコントロールが表示されます(ユーザーがアプリケーションの残りの部分にアクセスするのをブロックするという意味で)が、メソッドの呼び出しはブロックされないため、実行はすぐに続行されます。私の例では、ループが原因で複数のダイアログが表示される可能性があります。コレクションにオブジェクトを追加するだけで、この動作を変更できないため、このメソッドは非ブロッキングです。
ただし、Rxを使用したいので、ShowDialog
が返されるようにしましたIObservable
。そのため、メソッドはすぐに戻りますが、のアクションによって表示されたコントロールが閉じられるOnCompleted
と、オブザーバーを呼び出すオブジェクトがあります。それが重要な場合に備えて、ShowDialog
私はこれにを使用しています。Subject
私が今欲しいのは、これIObservable
が完了するのを待ってから先に進むことです。したがって、ブロッキング呼び出しをシミュレートします。FirstOrDefault
待機部分は正常に実行されますが、残念ながら、UIスレッドもブロックされ、コントロールが実際に表示されなくなり、ユーザーがコントロールを閉じることができなくなり、IObservable
完了できなくなります。
x秒後にダイアログを自動的に閉じることで、ある種の作業を行うことができるので、私の考えは遠くないことを知っています。今必要なのは、ユーザーがタイマーの代わりにコントロールを閉じることができるように、UIをブロックしない「待機」部分です。