3

同期メソッドでイベントをインスタンス化する ViewModel があります。このイベントは、続行する前にユーザーからの「はい」または「いいえ」の回答が必要であることを UI に通知します。

を表示してMessageDialog、ユーザーが「はい」または「いいえ」という回答を返すまで待ち​​ます。これを行うのに苦労しています。私は現在、UnauthorizedAccessExceptionこれをやろうとすると取得します。

UI のコードを次に示します。

async Task<bool> Instance_SwitchConfirmation(string question)
{
    MessageDialog md = new MessageDialog(question);
    md.Commands.Add(new UICommand("Yes", CommandInvokedHandler));
    md.Commands.Add(new UICommand("No", CommandInvokedHandler));
    md.ShowAsync();

    return this.canSwitch;
}

async void CommandInvokedHandler(IUICommand command)
{
    this.canSwitch = command.Label == "Yes" ? true : false;
}

私が試してみました:

var uiContext = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() => {
    MessageDialog md = new MessageDialog(question);
    md.Commands.Add(new UICommand("Yes", CommandInvokedHandler));
    md.Commands.Add(new UICommand("No", CommandInvokedHandler));
    md.ShowAsync();
}, 
new System.Threading.CancellationToken(), 
TaskCreationOptions.PreferFairness, uiContext);

しかし、これは同じ例外で失敗します。

最後に、このように MessageDialog を単に待機すると、ダイアログが表示されず、UI スレッドがロックされます。

MessageDialog md = new MessageDialog(question);
md.Commands.Add(new UICommand("Yes", CommandInvokedHandler));
md.Commands.Add(new UICommand("No", CommandInvokedHandler));
await md.ShowAsync();

IMessageDialogの同期バージョンがあれば問題ありませんが、同期ルーチンと組み合わせた非同期動作と、クロス スレッドとの組み合わせが混乱を招きます。バックエンドViewModelで同期メソッドを続行する前に、ユーザー入力を待つために何をする必要があるかを誰かが概説できるかどうか疑問に思っています。Show()MessageDialogMessageDialog

助けてくれてありがとう。

4

1 に答える 1

8

Win8 C# Metro ディスパッチャと RPC_E_WRONG_THREADおよびを参照してくださいCoreDispatcher.RunAsync

メソッドは で実行されていないDispatcherため、コードを手動で呼び出す必要があります。コールバック パターンへのリファクタリングを避けるために、 を使用しTaskCompletionSource(T)て結果を設定すると、結果が設定された後もバックグラウンド スレッドが続行されます。

var tcs = new TaskCompletionSource<bool>();
var dialogTask = tcs.Task;

MessageDialog md = new MessageDialog(question);
md.Commands.Add(new UICommand("Yes"));
md.Commands.Add(new UICommand("No"));

Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => {
    var result = await md.ShowAsync();
    var canSwitch = result.Label == "Yes";
    tcs.SetResult(canSwitch);
});

var result = await dialogTask;
return result;
于 2013-06-24T12:08:00.807 に答える