为什么这个任务等待离开Xamarin iOS中的UI上下文?
以下内容多少动摇了我基于异步/等待的信念体系。在Xamarin/iOS下,以下操作失败,说明与UI相关的事情是在非UI线程中完成的。添加检查点表明,在异步文件写入之后,上下文实际上会切换 我的理解是,缺少配置等待,以下应该是完全安全的。我假设这是一个我不知道的Xamarin的细微差别,但很难理解这可能是什么 同样的代码在Android和UWP上运行良好为什么这个任务等待离开Xamarin iOS中的UI上下文?,ios,xamarin,async-await,Ios,Xamarin,Async Await,以下内容多少动摇了我基于异步/等待的信念体系。在Xamarin/iOS下,以下操作失败,说明与UI相关的事情是在非UI线程中完成的。添加检查点表明,在异步文件写入之后,上下文实际上会切换 我的理解是,缺少配置等待,以下应该是完全安全的。我假设这是一个我不知道的Xamarin的细微差别,但很难理解这可能是什么 同样的代码在Android和UWP上运行良好 private async void ShareButton_OnClicked(object sender, EventArgs e) {
private async void ShareButton_OnClicked(object sender, EventArgs e)
{
if (!(BindingContext is PhotoViewModel photoViewModel))
{
return;
}
// in UI context
var name = photoViewModel.Name ?? "temp.jpg";
var file = Path.Combine(FileSystem.CacheDirectory, name);
using (var stream = new FileStream(file, FileMode.Create, FileAccess.Write))
{
await stream.WriteAsync(photoViewModel.Data, 0, photoViewModel.Data.Length);
}
// not in UI context!
// calling this causes SIGABRT: UIKit Consistency error
await Share.RequestAsync(new ShareFileRequest(new ShareFile(file)));
}
调用此函数会导致SIGABRT:UIKit一致性错误
虽然Android和UWP没有问题,但它可能与iOS中的这种书写方式不兼容。上面的代码需要UI线程来调用,但是它位于async
方法ShareButton\u OnClicked
中。可能需要特别从主线程调用它,请尝试使用以下代码来调用它
await Device.InvokeOnMainThreadAsync(() =>
{
// inkoke your code .
Share.RequestAsync(new ShareFileRequest(new ShareFile(file)));
});
调用此函数会导致SIGABRT:UIKit一致性错误
虽然Android和UWP没有问题,但它可能与iOS中的这种书写方式不兼容。上面的代码需要UI线程来调用,但是它位于async
方法ShareButton\u OnClicked
中。可能需要特别从主线程调用它,请尝试使用以下代码来调用它
await Device.InvokeOnMainThreadAsync(() =>
{
// inkoke your code .
Share.RequestAsync(new ShareFileRequest(new ShareFile(file)));
});
这原来是mono中的一个bug
这原来是mono中的一个bug
检查
SynchronizationContext.Current的值,然后在wait
之前检查该值。Xamarin应该在启动事件处理程序之前设置该值,以便在UI上下文上继续执行wait
。@StephenCleary当您说“检查值”时,我不确定我要查找的是什么。我确实尝试过调用MainThread.IsMainThread(一种Xamarin Essentials的东西,似乎在iOS上包装了NSThread),它在调用之前为true,在调用之后为false。当前上下文在这两种情况下都不是空的,但我不知道除此之外还要寻找什么。谢谢。检查它是否为null
,如果不是,它是什么类型。在它之前和之后都不是null,并且是UIKit.UIKITSynchronizationContext类型。那么,您应该与Xamarin团队联系。在wait
之前检查SynchronizationContext.Current
的值。Xamarin应该在启动事件处理程序之前设置该值,以便在UI上下文上继续执行wait
。@StephenCleary当您说“检查值”时,我不确定我要查找的是什么。我确实尝试过调用MainThread.IsMainThread(一种Xamarin Essentials的东西,似乎在iOS上包装了NSThread),它在调用之前为true,在调用之后为false。当前上下文在这两种情况下都不是空的,但我不知道除此之外还要寻找什么。谢谢。检查它是否为null
,如果不是,它是什么类型。在它之前和之后都不是null,并且是UIKit.UIKITSynchronizationContext类型。那么,您应该与Xamarin团队跟进。这就是我最终使用的内容,但我不明白为什么在iOS中无法正确设置上下文。简言之,为什么这是必要的,我如何知道这不会突然发生在其他处理程序中?@Jeff我已经检查了我的项目,没有问题。我想知道你的项目是否使用了最新版本的VS(16.3.10)/Forms(4.3.0.991221)和Essentials(1.3.1)。我开始认为这只是某种奇怪的Xamarin错误。这就是我最终使用的,但我不明白为什么在iOS中无法正确设置上下文。简言之,为什么这是必要的,我如何知道这不会突然发生在其他处理程序中?@Jeff我已经检查了我的项目,没有问题。我想知道你的项目是否使用了最新版本的VS(16.3.10)/Forms(4.3.0.991221)和Essentials(1.3.1)。我开始认为这只是某种奇怪的Xamarin bug