如何解决与 Dispatcher.PushFrame 等效的 Xamarin Forms 是什么?
我的 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 应用程序中使用类似的东西,以便能够使用相同的代码库。
这都是需要的,因为一个不支持 async/await 的 3rdparty 库。出于同样的原因,我不能只使用 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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。