我的 WPF 应用程序中有以下代码,用于从 UI 线程上的非异步函数调用并等待 asnyc 函数,而不会阻塞它。这是通过使用 DispatcherFrame 在后台泵送消息来完成的:
public static void WaitWithPumping(this Task task)
{
if (task == null) throw new ArgumentNullException(“task”);
var nestedFrame = new DispatcherFrame();
task.ContinueWith(_ => nestedFrame.Continue = false);
Dispatcher.PushFrame(nestedFrame);
task.Wait();
}
public static T ResultWithPumping<T>(this Task<T> task)
{
if (task == null) throw new ArgumentNullException(“task”);
var nestedFrame = new DispatcherFrame();
task.ContinueWith(_ => nestedFrame.Continue = false);
Dispatcher.PushFrame(nestedFrame);
return task.Result;
}
我想在我的 Xamarin Forms iOS/Android 应用程序中使用类似的东西,以便能够使用相同的代码库。
由于第三方库不支持异步/等待,所以这一切都是必需的。出于同样的原因,我不能只使用 Task.Run() 或 ConfigureAwait(false),因为这些函数需要在 UI 上运行,并且我需要等待结果,然后才能从同一阻塞函数启动下一个任务。
public async void RunTaskOnUi1Async()
{
await ProcessAsync();
UpdateUiInner();
}
public async object RunTaskOnUi2Async()
{
var result = await ProcessAsync();
UpdateUiInner(result);
return result;
}
// Called from the UI thread
public void RunTasks()
{
UpdateUi();
RunTaskOnUi1Async().WaitWithPumping();
UpdateUi();
var result = RunTaskOnUi2Async().ResultWithPumping();
UpdateUi(result);
}
编辑 #1:更新示例。我知道这个例子有点蹩脚。为什么不将 RunTasks 更改为异步?或者只是在后台线程上运行 ProcessAsync() ?嗯,我正在开发一个遗留项目(当然),RunTasks 是一个 LUA 脚本处理引擎,它调用我的 C# 代码并直接操作 UI,因此它必须在 UI 线程上运行,并且设计上是非异步的。改变它将是一项艰巨的工作。但我的其余代码是异步的,我可以通过使用消息泵方法轻松解决 WPF 中的这个问题。
最佳答案
尝试下面的代码:
public static Task<T> BeginInvokeOnMainThreadAsync<T>(Func<T> a)
{
var tcs = new TaskCompletionSource<T>();
Device.BeginInvokeOnMainThread(() =>
{
try
{
var result = a();
tcs.SetResult(result);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
});
return tcs.Task;
}
关于c# - Dispatcher.PushFrame 的 Xamarin Forms 等效项是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67606128/