为什么这个任务等待离开Xamarin iOS中的UI上下文?

为什么这个任务等待离开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) {

以下内容多少动摇了我基于异步/等待的信念体系。在Xamarin/iOS下,以下操作失败,说明与UI相关的事情是在非UI线程中完成的。添加检查点表明,在异步文件写入之后,上下文实际上会切换

我的理解是,缺少配置等待,以下应该是完全安全的。我假设这是一个我不知道的Xamarin的细微差别,但很难理解这可能是什么

同样的代码在Android和UWP上运行良好

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