我正在开发一个 WPF XBAP 应用程序,它使用 BrowserInteropHelper 通过 JavaScript 向用户提供 API。在以新的 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 是 async 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;
}