Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Async task continues on wrong (non-UI) context #8747

Closed
jefffhaynes opened this issue Dec 4, 2019 · 7 comments
Closed

Async task continues on wrong (non-UI) context #8747

jefffhaynes opened this issue Dec 4, 2019 · 7 comments
Labels
s/needs-info ❓ A question has been asked that requires an answer before work can continue on this issue. s/needs-repro ❔ This reported issue doesn't include a sample project reproducing the issue. Please provide one. s/unverified New report that has yet to be verified t/bug 🐛

Comments

@jefffhaynes
Copy link

The following has somewhat shaken my async/await-based belief system. Under Xamarin/iOS the following fails, saying that UI-related things are being done in a non-UI thread. Adding check points shows that the context does in fact switch after the async file write.

My understanding is that lacking a ConfigureAwait, the following should be completely safe. I'm assuming this is a Xamarin nuance of which I'm unaware but it's difficult to understand what that could be.

This same code works fine on Android and 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)));
}
@jefffhaynes jefffhaynes added s/unverified New report that has yet to be verified t/bug 🐛 labels Dec 4, 2019
@borrrden
Copy link

borrrden commented Dec 5, 2019

Check to make sure SynchronizationContext.Current is set to an instance of UIKitSynchronizationContext as a sanity check (not that you need to set it yourself, but if it is not set that would be a giant red flag and probably an easy fix).

@jefffhaynes
Copy link
Author

It is, both before and after

@borrrden
Copy link

borrrden commented Dec 5, 2019

Well that is certainly interesting. It suggests that you are indeed back on the same thread you started on since there is only one instance of that context being used in the entire codebase of the Xamarin iOS runtime (During the initial call to main). But you have confirmed that the managed thread is actually different?

All async/await does is start off a task on the thread pool with some custom logic in its ContinueWith method which checks the synchronization context. If it is null, then it just runs the rest of the method as a block inside of ContinueWith, otherwise it calls the Post method of synchronization context (which in this case, will call NSRunLoop.Main.BeginInvokeOnMainThread)

If it is having issues, as a workaround you could try calling SynchronizationContext.Current.Post(Share.RequestAsync(new ShareFileRequest(new ShareFile(file))));

@jefffhaynes
Copy link
Author

I haven’t checked the managed thread but calling MainThread.IsMainThread (from Xamarin Essentials) shows true before the async write and false after.

I can of course fix it by moving back into the UI context but I find it very worrying and I’m left wondering if similar behavior could pop up elsewhere.

Thanks

@PureWeen
Copy link
Contributor

PureWeen commented Dec 5, 2019

@jefffhaynes are you on the latest version of Visual Studio?

This was a known issue for a brief time with mono
mono/mono#16759

@PureWeen PureWeen added s/needs-info ❓ A question has been asked that requires an answer before work can continue on this issue. s/needs-repro ❔ This reported issue doesn't include a sample project reproducing the issue. Please provide one. labels Dec 5, 2019
@jefffhaynes
Copy link
Author

I’m using app center to build so I’m not sure. I’ll see if I can find it in the logs.

@jefffhaynes
Copy link
Author

I think you're right. I'll try to get them to update...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
s/needs-info ❓ A question has been asked that requires an answer before work can continue on this issue. s/needs-repro ❔ This reported issue doesn't include a sample project reproducing the issue. Please provide one. s/unverified New report that has yet to be verified t/bug 🐛
Projects
None yet
Development

No branches or pull requests

3 participants