BrowserInteropHelperを使用してJavaScriptを介してユーザーにAPIを提供するWPFXBAPアプリケーションを開発しています。管理対象部分を新しいasync-await方式で書き換えた後、メソッドasync Task自体を呼び出さずに、非同期操作が終了するまで待機する必要があります。私は持っています :
public string SyncMethod(object parameter)
{
var sender = CurrentPage as MainView; // interop
var result = string.Empty;
if (sender != null)
sender.Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(async () =>
{
try
{
result = await sender.AsyncMethod(parameter.ToString());
}
catch (Exception exception)
{
result = exception.Message;
}
}));
return result;
}
このメソッドはstring.Emptyを返します。これは、実行直後に発生するためです。このアクションをDispatcherOperationに割り当てて、while(dispatcherOperation.Status!= Completed){Wait();を実行しようとしました。}ですが、実行後も値は空です。dispatcherOperation.Task.Wait()またはdispatcherOperation.Task.ContinueWith()も役に立ちませんでした。
編集
も試してみました
var op = sender.Dispatcher.BeginInvoke(...);
op.Completed += (s, e) => { var t = result; };
ただし、非同期メソッドを待つ前に割り当てが行われるため、tも空です。
簡単に言うと、SyncMethod JavaScript相互運用ハンドラヘルパーラッパーを
編集し、実行するすべての操作はDispatcherで行う必要があります。
AsyncMethodは非同期Task<T>であり、アプリケーション内、つまりボタンハンドラー内から実行および待機されたときに完全に機能します。UIに依存するロジックがたくさんあります(ステータスの進行状況バーの表示、カーソルの変更など)。
AsyncMethod
を編集します:
public async Task<string> AsyncMethod(string input)
{
UIHelpers.SetBusyState(); // overriding mouse cursor via Application.Current.Dispatcher
ProgressText = string.Empty; // viewmodel property reflected in ui
var tasksInputData = ParseInput(input);
var tasksList = new List<Task>();
foreach (var taskInputDataObject in tasksInputData)
{
var currentTask = Task.Factory.StartNew(() =>
{
using (var a = new AutoBusyHandler("Running operation" + taskInputData.OperationName))
{ // setting busy property true/false via Application.Current.Dispatcher
var databaseOperationResult = DAL.SomeLongRunningMethod(taskInputDataObject);
ProgressText += databaseOperationResult;
}
});
tasksList.Add(insertCurrentRecordTask);
}
var allTasksFinished = Task.Factory.ContinueWhenAll(tasksList.ToArray(), (list) =>
{
return ProgressText;
});
return await allTasksFinished;
}