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

ImageSource.LoadImage callback is never invoked on Windows #6638

Closed
dharber opened this issue Apr 28, 2022 · 6 comments
Closed

ImageSource.LoadImage callback is never invoked on Windows #6638

dharber opened this issue Apr 28, 2022 · 6 comments
Assignees
Labels
area-controls-image Image control p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint platform/windows 🪟 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Milestone

Comments

@dharber
Copy link

dharber commented Apr 28, 2022

Description

Perhaps I'm misunderstanding what ImageSource.LoadImage does but I've been trying to use it to insure the image is loaded before setting it as a source to an Image control in an attempt to minimize the latency between setting the source and the image appearing. (These are UriImageSource's, btw.)

It seemed to sort of work on Android in Preview 14 but it's not clear it's actually loading anything on main currently. However, on Android, at least the callback gets fired. On Windows, it never does. I think it sort of did on Windows in Preview 14 but I might be misremembering. Loading images from URI's on Windows has been painfully slow in MAUI for some time. It actually seems like all network access is much slower than it should be on Windows but that's another topic.

Anyway, I'm not 100% sure it ever worked but the callback is definitely never firing now in main.

Steps to Reproduce

MainPage.xaml:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ImageTest2.MainPage">
			 
    <ScrollView>
        <VerticalStackLayout 
            Spacing="25" 
            Padding="30,0" 
            VerticalOptions="Center">

            <Image
                x:Name="Image"
                Source="dotnet_bot.png"
                SemanticProperties.Description="Cute dot net bot waving hi to you!"
                HeightRequest="200"
                HorizontalOptions="Center" />
                
            <Label 
                Text="Hello, World!"
                SemanticProperties.HeadingLevel="Level1"
                FontSize="32"
                HorizontalOptions="Center" />
            
            <Label 
                Text="Welcome to .NET Multi-platform App UI"
                SemanticProperties.HeadingLevel="Level2"
                SemanticProperties.Description="Welcome to dot net Multi platform App U I"
                FontSize="18"
                HorizontalOptions="Center" />

        </VerticalStackLayout>
    </ScrollView>
 
</ContentPage>

MainPage.xaml.cs:

namespace ImageTest2;

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        imageTimer = new(Timer_Tick, null, 1000, 1000);
    }

    private void Timer_Tick(object _)
    {
        var imageSource = ImageSource.FromUri(new Uri(images[imageNo]));
        imageSource.LoadImage(Image.Handler.MauiContext, _ =>
        {
            Application.Current.Dispatcher.Dispatch(() => Image.Source = imageSource);
            imageNo = (imageNo + 1) % images.Length;
        });
    }

    readonly string[] images = new string[]
    {
        "https://64.media.tumblr.com/14cb5aa197e5d9ca6479d955f68344f0/cb28a32e384437f2-07/s540x810/005508be5849eff8fda5b0ebda23f9fcbede164e.jpg",
        "https://64.media.tumblr.com/d66b1709639c23315d26c0a4e977c399/1fb3e31c5e63625d-81/s540x810/2e9a893ec8c1f65a4b9fb8f1264b4fb76914ced8.jpg",
        "https://64.media.tumblr.com/e7db300b8248c0a7f4c66884032c9414/8f89498ebe784d1c-4e/s540x810/90835c041547bf2936ee249c5c5e1b4eddd589a3.jpg",
        "https://64.media.tumblr.com/fd901060692d2c9ca6f05ddc58e28e5d/2db73c9c5730d87c-e2/s500x750/092c9dc3cff5150acf24bf22a9e61b9719d9ccd6.jpg",
        "https://64.media.tumblr.com/c011aa547a45ac6fe47c46beeb290596/eafc76ded66f16f9-dc/s500x750/5ed923ed086296a2bd41cab3106079eb7addc2d0.jpg",
    };
    int imageNo = 0;
    readonly Timer imageTimer;
}

Version with bug

Release Candidate 3

Last version that worked well

Unknown/Other

Affected platforms

Windows

Affected platform versions

Windows 10, not sure which SDK is being used and not sure how to check

Did you find any workaround?

No workaround found using MAUI

Relevant log output

n/a
@dharber dharber added s/needs-verification Indicates that this issue needs initial verification before further triage will happen t/bug Something isn't working labels Apr 28, 2022
@Eilon Eilon added the area-image Image loading, sources, caching label Apr 28, 2022
@XamlTest XamlTest added s/verified Verified / Reproducible Issue ready for Engineering Triage s/triaged Issue has been reviewed and removed s/needs-verification Indicates that this issue needs initial verification before further triage will happen labels Apr 29, 2022
@XamlTest
Copy link

Verified this issue with Visual Studio Enterprise 17.3.0 Preview 1.0 [32427.455.main]. Repro on Windows. Sample Project: 6638.zip

@Redth
Copy link
Member

Redth commented May 3, 2022

In main the callback is happening just fine on android, but I can see the same behaviour on windows where it is not called.

@Redth Redth added this to the 6.0.300 milestone May 3, 2022
@Redth Redth added p/0 Work that we can't release without p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint and removed p/0 Work that we can't release without labels May 3, 2022
@kristinx0211
Copy link

still an issue on windows with 17.3.0 Preview 2.0 [32507.29.main].

@samhouts samhouts modified the milestones: 6.0.300, 6.0.300-servicing May 12, 2022
@mattleibow
Copy link
Member

This is because loading an image on windows actually creates a native ImageSource - which requires that it be done on the main thread. Timers use a background thread.

One workaround is to wrap the call in a Dispatcher.Dispatch():

private void Timer_Tick(object _)
{
	Dispatcher.Dispatch(() =>
	{
		var imageSource = ImageSource.FromUri(new Uri(images[imageNo]));
		imageSource.LoadImage(Image.Handler.MauiContext, _ =>
		{
			Application.Current.Dispatcher.Dispatch(() => Image.Source = imageSource);
			imageNo = (imageNo + 1) % images.Length;
		});
	});
}

But, and even better and specifically designed for this scenario is to use the dispatcher timers:

readonly IDispatcherTimer imageTimer;

int imageNo = 0;

public MainPage()
{
	InitializeComponent();

	imageTimer = Dispatcher.CreateTimer();
	imageTimer.Tick += Timer_Tick;
	imageTimer.Interval = TimeSpan.FromSeconds(1);
	imageTimer.Start();
}

void Timer_Tick(object sender, EventArgs e)
{
	var imageSource = ImageSource.FromUri(new Uri(images[imageNo]));
	imageSource.LoadImage(Image.Handler.MauiContext, _ =>
	{
		Dispatcher.Dispatch(() => Image.Source = imageSource);
		imageNo = (imageNo + 1) % images.Length;
	});
}

readonly string[] images = new string[]
{
	"https://64.media.tumblr.com/14cb5aa197e5d9ca6479d955f68344f0/cb28a32e384437f2-07/s540x810/005508be5849eff8fda5b0ebda23f9fcbede164e.jpg",
	"https://64.media.tumblr.com/d66b1709639c23315d26c0a4e977c399/1fb3e31c5e63625d-81/s540x810/2e9a893ec8c1f65a4b9fb8f1264b4fb76914ced8.jpg",
	"https://64.media.tumblr.com/e7db300b8248c0a7f4c66884032c9414/8f89498ebe784d1c-4e/s540x810/90835c041547bf2936ee249c5c5e1b4eddd589a3.jpg",
	"https://64.media.tumblr.com/fd901060692d2c9ca6f05ddc58e28e5d/2db73c9c5730d87c-e2/s500x750/092c9dc3cff5150acf24bf22a9e61b9719d9ccd6.jpg",
	"https://64.media.tumblr.com/c011aa547a45ac6fe47c46beeb290596/eafc76ded66f16f9-dc/s500x750/5ed923ed086296a2bd41cab3106079eb7addc2d0.jpg",
};

An even more "but" here is not not do any of this as it does not actually guarantee the image has loaded into memory. Rather, it loads the platform representation of the image - which on Windows is just a wrapper for a URI that is then loaded at the OS' discretion. In fact, nice you fix the code to load images, you can see that it is flickering between loaded and unloaded as the image is changed, but not actually in memory.

Even on other platforms, this method of loading images does not actually improve UX because if an image takes about 1s to load, then it will flip between the 2 images almost instantaneously as when the first image is finally loaded and set, the timer may have ticked and then immediately loaded the next one.

It appears this approach of loading images was originally implemented to improve the UX when switching images. And I believe this may be a result of the act that setting the source clears the previous image? If this is the case, please open another issue describing if this is the issue and what you would suggest. The old image remains? A loading image?

@dharber
Copy link
Author

dharber commented May 19, 2022

Yeah, I wasn't sure if the callback actually represented the image being loaded and decoded, etc. But it did seem to improve the experience so I used it. I'm assuming there's some set of API's, perhaps platform-dependent, where I can fetch the bytes and decode the image and know when it's ready to display but I was unable to find it.

I don't know what the appropriate behavior is, really. All I know is it worked more or less exactly like I wanted/expected in Preview 14 then everything was broken in the release candidate(s). Granted, there were still potential erratic delays in images being displayed based on latency and decoding issues but at least it was close and there was no noticeable flicker.

@mattleibow
Copy link
Member

I think this is your other issue? #6625

Going to move the discussion there.

@ghost ghost locked as resolved and limited conversation to collaborators Jun 19, 2022
@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 p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint platform/windows 🪟 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

7 participants