Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only the original thread that created a view hierarchy can touch its view #14052

Closed
williambuchanan2 opened this issue Mar 19, 2023 · 34 comments · Fixed by #14109
Closed

Only the original thread that created a view hierarchy can touch its view #14052

williambuchanan2 opened this issue Mar 19, 2023 · 34 comments · Fixed by #14109
Labels
area-controls-image Image control fixed-in-7.0.96 Look for this fix in 7.0.96 SR8! fixed-in-7.0.100 fixed-in-7.0.101 fixed-in-8.0.0-preview.5.8529 Look for this fix in 8.0.0-preview.5.8529! platform/android 🤖 t/bug Something isn't working

Comments

@williambuchanan2
Copy link

Description

I seem to have an unhandled exception in Android when showing images on a page. The error is:

Android.Util.AndroidRuntimeException: 'Only the original thread that created a view hierarchy can touch its views.'

image

Steps to Reproduce

Open the project in the repository below.
Run the project and click the "Image Error" button.
This will open a page which downloads some images from a web API.
Scroll up and down the page a few times. Eventually the error will occur.

Link to public reproduction project repository

https://github.com/williambuchanan2/MauiNavigation

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android 11 and 13

Did you find any workaround?

No. Unable to proceed with project so this is a blocking problem.

Relevant log output

No response

@williambuchanan2 williambuchanan2 added the t/bug Something isn't working label Mar 19, 2023
@jsuarezruiz jsuarezruiz added platform/android 🤖 area-image Image loading, sources, caching labels Mar 20, 2023
@jsuarezruiz jsuarezruiz added this to the Backlog milestone Mar 20, 2023
@ghost
Copy link

ghost commented Mar 20, 2023

We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.

@jstedfast
Copy link
Member

It looks like a worker thread is trying to load image content into an Android.Widget.ImageView which, of course, fails because it's not being loaded in the main (UI) thread.

@williambuchanan2
Copy link
Author

I originally had the content being loaded in the main thread but ran into another problem and was advised not to do that. So I now move it into an async call but end up with this issue. Any advice on how to work around this for now?

@jstedfast
Copy link
Member

As far as I can tell, your code isn't doing anything wrong. From what I can tell, you async fetch the Feed collection but it gets set properly in the main (UI) thread, which means (or should mean?) that the MAUI Image controls should be getting created in the main UI thread and the bindings for the image data should be getting loaded in the main (UI) thread, but clearly that's not happening and I can't explain why (I'm brand new to the team and this is my second bug I'm looking at, so that's not saying much).

@jstedfast
Copy link
Member

Let me paste the call stack for continued reference (maybe someone else on the team can help point me in the right direction):

 	0xFFFFFFFFFFFFFFFF in Android.Runtime.JNIEnv.monodroid_debugger_unhandled_exception	C#
 	0x1A in Android.Runtime.JNINativeWrapper._unhandled_exception at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:12,5	C#
 	0x1D in Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:23,26	C#
 	0x17 in System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw	C#
 	0x89 in Java.Interop.JniEnvironment.InstanceMethods.CallNonvirtualVoidMethod at /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/obj/Release/net7.0/JniEnvironment.g.cs:12324,5	C#
 	0x78 in Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualVoidMethod at /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:75,7	C#
 	0x12 in Android.Views.View.RequestLayout at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net7.0/android-33/mcw/Android.Views.View.cs:20879,5	C#
 	0x8 in Microsoft.Maui.Platform.WrapperView.RequestLayout at D:\a\_work\1\s\src\Core\src\Platform\Android\WrapperView.cs:89,4	C#
 	0x8 in Android.Views.View.n_RequestLayout at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net7.0/android-33/mcw/Android.Views.View.cs:20869,4	C#
 	0x8 in Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:22,5	C#
 	0x37 in Java.Interop.NativeMethods.java_interop_jnienv_call_static_void_method_a	C#
 	0x54 in Java.Interop.JniEnvironment.StaticMethods.CallStaticVoidMethod at /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/obj/Release/net7.0/JniEnvironment.g.cs:13246,4	C#
 	0x1A in Java.Interop.JniPeerMembers.JniStaticMethods.InvokeVoidMethod at /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniStaticMethods.cs:97,4	C#
 	0x7B in Microsoft.Maui.PlatformInterop.LoadImageFromStream at D:\a\_work\1\s\src\Core\src\obj\Release\net7.0-android\generated\src\Microsoft.Maui.PlatformInterop.cs:443,5	C#
 	0xC8 in Microsoft.Maui.StreamImageSourceService.LoadDrawableAsync at D:\a\_work\1\s\src\Core\src\ImageSources\StreamImageSourceService\StreamImageSourceService.Android.cs:28,6	C#
 	0x11 in System.Runtime.CompilerServices.AsyncTaskMethodBuilder<Microsoft.Maui.IImageSourceServiceResult>.AsyncStateMachineBox<Microsoft.Maui.StreamImageSourceService.<LoadDrawableAsync>d__0>.ExecutionContextCallback	C#
 	0x17 in System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop	C#
 	0x55 in System.Runtime.CompilerServices.AsyncTaskMethodBuilder<Microsoft.Maui.IImageSourceServiceResult>.AsyncStateMachineBox<Microsoft.Maui.StreamImageSourceService.<LoadDrawableAsync>d__0>.MoveNext	C#
 	0x2 in System.Runtime.CompilerServices.AsyncTaskMethodBuilder<Microsoft.Maui.IImageSourceServiceResult>.AsyncStateMachineBox<Microsoft.Maui.StreamImageSourceService.<LoadDrawableAsync>d__0>.ExecuteFromThreadPool	C#
 	0xC in System.Threading.ThreadPoolWorkQueue.DispatchWorkItem	C#
 	0x142 in System.Threading.ThreadPoolWorkQueue.Dispatch	C#
 	0x67 in System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart	C#
 	0x1F in System.Threading.Thread.StartHelper.RunWorker	C#
 	0x28 in System.Threading.Thread.StartHelper.Run	C#
 	0xF in System.Threading.Thread.StartCallback	C#

jstedfast added a commit that referenced this issue Mar 21, 2023
Transition back to the calling thread context (which should theoretically be the main thread).

Fixes issue #14052
@williambuchanan2
Copy link
Author

Oh, fixed!? Good job getting that done so quickly.

Any idea on rough timeline for when it will be released?

jstedfast added a commit that referenced this issue Mar 23, 2023
Transition back to the calling thread context (which should theoretically be the main thread).

Fixes issue #14052
jstedfast added a commit that referenced this issue Mar 24, 2023
Transition back to the calling thread context (which should theoretically be the main thread).

Fixes issue #14052
jstedfast added a commit that referenced this issue Mar 27, 2023
Transition back to the calling thread context (which should theoretically be the main thread).

Fixes issue #14052
@wheric
Copy link

wheric commented Apr 11, 2023

Oh, fixed!? Good job getting that done so quickly.

Any idea on rough timeline for when it will be released?

I'm having this same issue and exception with image views. How would you upgrade Maui if a fix gets released? Have you been able to do so yet?

@williambuchanan2
Copy link
Author

No I am still having the issue. I can't release until this is fixed. I hoped it would have been released by now but not sure how to tell when or if it is getting released.

@wheric
Copy link

wheric commented Apr 11, 2023

No I am still having the issue. I can't release until this is fixed. I hoped it would have been released by now but not sure how to tell when or if it is getting released.

Actually shortly after I wrote that message I noticed there was a 7.0.81 Service Release today. I installed that and I can't seem to get the exception to reoccur. https://github.com/dotnet/maui/releases/tag/7.0.81

@williambuchanan2
Copy link
Author

Oh, thanks for the update, anthough I can't see #14052 listed on that page...

@wheric
Copy link

wheric commented Apr 12, 2023

Oh, thanks for the update, anthough I can't see #14052 listed on that page...

I looked for that bug fix number too but even though I didn't see it I thought I would try it anyway. Let me know if you try it as I may be missing a scenario. I still cannot reproduce the crash which was quite easy to create before.

@williambuchanan2
Copy link
Author

I just had a play and also seems to be ok for me. However I have found it to be intermittent in the past so will need to give it a few days before declaring that it is fixed!

@williambuchanan2
Copy link
Author

Uh spoke too soon. It just happened again, so clearly it hasn't been released yet :(

image

@wheric
Copy link

wheric commented Apr 12, 2023

Uh spoke too soon. It just happened again, so clearly it hasn't been released yet :(

I have tested many more times and still can't get a reproduction when I could reproduce 100% of the time before. Are your workload versions similar to mine?

image

@williambuchanan2
Copy link
Author

Looks like I am on the same Android version as you...

image

@xgabri18
Copy link

xgabri18 commented Apr 19, 2023

This issue came up for me from the MAUI version 7.0.59 while in 7.0.58 it worked.
I tested it by adding this line to the .csproj:
<MauiVersion>7.0.59</MauiVersion>

  • changing MAUI version like this worked even with MAUI workload 7.0.81 in VS 17.5.4 installed

In my case I have a collectionview showing pictures in contentview containing Image as control with source

public partial class FrameImage : ContentView
{
	public FrameImage()
	{
		InitializeComponent();
        Source = ImageSource.FromStream(() => new MemoryStream(SourceBytes));
    }

    public static readonly BindableProperty SourceBytesProperty = BindableProperty.Create(nameof(SourceBytes), typeof(byte[]), typeof(FrameImage));

    public byte[] SourceBytes
    {
        get => (byte[])GetValue(SourceBytesProperty);
        set => SetValue(SourceBytesProperty, value);

    }

    private ImageSource source;
    public ImageSource Source
    {
        get => source;
        set
        {
            OnPropertyChanging(nameof(Source));
            source = value;
            OnPropertyChanged(nameof(Source));
        }
    }

    protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        base.OnPropertyChanged(propertyName);

        if (propertyName == nameof(SourceBytes))
        {
            Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
            Device.InvokeOnMainThreadAsync(() => Source = ImageSource.FromStream(() => new MemoryStream(SourceBytes)));
        }
    }

}

It happens when I remove an item from the CollectionView and try to add a new one.

The CollectionView itemtemplate:

<CollectionView.ItemTemplate>
                    <DataTemplate x:DataType="models:FotoDTO">
                        <Grid RowDefinitions="Auto" ColumnDefinitions="*" Padding="8">
                                <controls:FrameImage SourceBytes="{Binding Data}"/>

                            </Grid>

                    </DataTemplate>
</CollectionView.ItemTemplate>

@jstedfast
Copy link
Member

Hey guys, my patch still hasn't been merged so it's not yet in any released version.

@janseris
Copy link

janseris commented Apr 19, 2023

Hey guys, my patch still hasn't been merged so it's not yet in any released version.

The comment was about that it is a regression bug - it only appeared since 7.0.59 and did not appear in 7.0.58.
This means that the bug was introduced in 7.0.59 patch.

@jstedfast
Copy link
Member

I know it seems that way to you based on your test case, but it has existed for a while now.

My patch solves this by making sure that the image data gets set on the Android Image control in the main thread consistently.

The current code does not always context switch back to the main thread when setting that image data.

Note that I said "doesn't always", meaning sometimes the current code does the right thing but it is through "luck".

You got lucky with 7.0.58 and are unlucky with 7.0.59.

@janseris
Copy link

Happened now to me randomly when zooming an image by hand using the pinch & zoom control from official documentation (https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/gestures/pinch)

<views:PinchToZoomContainer
               IsVisible="{Binding IsLoading, Converter={StaticResource BoolToInverseBoolConverter}}"
               VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
            >
            <Image Source="{Binding Data, Converter={StaticResource ByteArrayToImageSourceConverter}}" 
               IsVisible="{Binding IsLoading, Converter={StaticResource BoolToInverseBoolConverter}}"
               VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
               >
                <!-- horizontal orientation bug: https://github.com/dotnet/maui/issues/15023 -->
                <Image.Shadow>
                    <Shadow Brush="{StaticResource BlackBrush}" Offset="10,10" Radius="10" Opacity="0.5" />
                </Image.Shadow>
            </Image>
        </views:PinchToZoomContainer>

@williambuchanan2
Copy link
Author

Happened now to me randomly when zooming an image by hand using the pinch & zoom control from official documentation (https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/gestures/pinch)

Yeah supposedly 'fixed' nearly 2 months ago but still happening.

@jstedfast
Copy link
Member

My patch to fix this still hasn't been merged. Hopefully soon.

@williambuchanan2
Copy link
Author

My patch to fix this still hasn't been merged. Hopefully soon.

Thanks for the update. If it takes this long then it doesn't bode well for the multitude of critical bugs which haven't even been looked at yet!

@sbloom82
Copy link

I ran into this issue as well. Understanding what was happening took a while, but it seemed to occur when updating an ImageSource in a control I created. When setting the image source a second time, I would encounter the "Only the original thread that created a view hierarchy can touch its views." error message and an app crash.

I was able to work around this issue by removing the control (in my case an ImageButton) from its parent, creating a new one with the updated Source, and then adding that back to the parent control.

@janseris
Copy link

I ran into this issue as well. Understanding what was happening took a while, but it seemed to occur when updating an ImageSource in a control I created. When setting the image source a second time, I would encounter the "Only the original thread that created a view hierarchy can touch its views." error message and an app crash.

I was able to work around this issue by removing the control (in my case an ImageButton) from its parent, creating a new one with the updated Source, and then adding that back to the parent control.

For me that happened super randomly in 1 case of 1000, did that happen for you in 100 % cases? Also the issue in my case was that I was not using another thread.

@williambuchanan2
Copy link
Author

For me that happened super randomly in 1 case of 1000, did that happen for you in 100 % cases? Also the issue in my case was that I was not using another thread.

Are you sure you are looking at the same problem? This is something that happens pretty much 100% of the time for me, on every page I have an image button or an image. To me it looks like a problem with scrolling because it seems to happen while the page with the image scrolls.

@williambuchanan2
Copy link
Author

So, I downloaded the latest VS update this morning. I see now that the error message is the same, but it is at least showing some code now when it happens (not that this helps in any way...):

Screenshot_2

@Strypper
Copy link

I got this issue also when I fired MVVM Message and setting the Imagesource inside the subscribe event

    void SubcribeForNewPetCreation()
    {
        WeakReferenceMessenger.Default.Register<CreatePetMessageModel>(this, (_, message) =>
        {
            MainThread.BeginInvokeOnMainThread(async () =>
            {

                var pet = message;
                var speciesGroupName = pet.speciesName;
                var species = Items.FirstOrDefault(species => species.SpeciesName.Equals(speciesGroupName));
                if (species is null)
                    return;


                var petProfileForUpdateUI = mapper.Map<PetProfileCardModel>(pet);
                petProfileForUpdateUI.PetAvatar = await ConvertFileResultToImageSource(pet.petAvatar);
                species.Add(petProfileForUpdateUI);

                var petProfileForServer = mapper.Map<CreateAnimalDTO>(pet);
                petProfileForServer.AvatarFile = await ConvertFileResultToStreamPart(pet.petAvatar);
                await animalService.CreateAsync(petProfileForServer);
            });
        });
    }
    async Task<StreamPart> ConvertFileResultToStreamPart(FileResult file)
    {
        using (var fileBytes = await file.OpenReadAsync())
        {
            return new StreamPart(fileBytes, file.ContentType);
        }
    }

    async Task<ImageSource> ConvertFileResultToImageSource(FileResult file)
    {
        MemoryStream memoryStream = new MemoryStream();
        await file.OpenReadAsync().ContinueWith((t) =>
        {
            var stream = t.Result;
            stream.CopyTo(memoryStream);
            memoryStream.Position = 0;
        });
        return ImageSource.FromStream(() => new MemoryStream(memoryStream.ToArray()));
    }

jstedfast added a commit that referenced this issue May 22, 2023
Transition back to the calling thread context (which should theoretically be the main thread).

Fixes issue #14052
@AntunTkalcec
Copy link

Still happening when binding an Image's Source to something. A simple refresh of a user's profile (which in turn updates their profile picture byte[]) crashes the app.

@samhouts samhouts modified the milestones: Backlog, .NET 8 May 24, 2023
rmarinho pushed a commit that referenced this issue May 30, 2023
Transition back to the calling thread context (which should theoretically be the main thread).

Fixes issue #14052
@fgiacomelli
Copy link

same problem for me, happening when I update the imagesource of an avatarview.
Solved following this suggestion: #13904 (comment)

@samhouts samhouts added the fixed-in-8.0.0-preview.5.8529 Look for this fix in 8.0.0-preview.5.8529! label Jun 21, 2023
@williambuchanan2
Copy link
Author

@samhouts @jstedfast - I don't get it. This was marked as fixed in March. It's still happening. That's 3 months of waiting so I am not convinced that the problem is actually fixed.

@janseris
Copy link

janseris commented Jun 30, 2023

@williambuchanan2 as mentioned here #15397, the planned release is for .NET 8 Preview 5 but I cannot find any .NET 7 release.
This probably means that it will be available in November 2023 (hilarious).

@williambuchanan2
Copy link
Author

@williambuchanan2 as mentioned here #15397, the planned release is for .NET 8 Preview 5 but I cannot find any .NET 7 release. This probably means that it will be available in November 2023 (hilarious).

I'm sure nobody will mind that you can't put images into Maui apps. Stupid of me to think this would ever have been possible.

@ghost ghost locked as resolved and limited conversation to collaborators Jul 31, 2023
@samhouts samhouts added the fixed-in-7.0.96 Look for this fix in 7.0.96 SR8! label Oct 10, 2023
@Eilon Eilon added area-controls-image Image control and removed area-image Image loading, sources, caching labels May 10, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-controls-image Image control fixed-in-7.0.96 Look for this fix in 7.0.96 SR8! fixed-in-7.0.100 fixed-in-7.0.101 fixed-in-8.0.0-preview.5.8529 Look for this fix in 8.0.0-preview.5.8529! platform/android 🤖 t/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.