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

Loading image fails #9342

Closed
usdarmy opened this issue Feb 16, 2024 · 5 comments
Closed

Loading image fails #9342

usdarmy opened this issue Feb 16, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@usdarmy
Copy link

usdarmy commented Feb 16, 2024

Describe the bug

I'm developing an application in WinUI 3, and I'm experiencing random failures when loading an image from disk into the Image element. There is a binding between the Source property of the Image element and the ViewModel.

Steps to reproduce the bug

<Image Source="{Binding MainImageSource}" />
private BitmapImage mainImageSource = null;
public BitmapImage MainImageSource
{
    get => mainImageSource;
    set
    {
        mainImageSource = value;
        OnPropertyChanged(nameof(MainImageSource));
    }
}
MainImageSource = await GetImageSourceFromAssets("quiz_intro_main.png");
private static async Task<BitmapImage> GetImageSourceFromAssets(string path)
{
    StorageFile file = await StorageFile.GetFileFromPathAsync(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Assets\\{path}"));
    using IRandomAccessStream fileStream = await file.OpenReadAsync();
    BitmapImage bitmapImage = new();
    await bitmapImage.SetSourceAsync(fileStream);

    return bitmapImage;
}

If I repeatedly set the MainImageSource property, the image randomly fails to display, and a white screen remains.

I have created a proof of concept where the described behavior can be reproduced. Clicking within the application loads another image. If I click repeatedly (sometimes even longer than a minute, patience is required), the image fails to load. In the debugger, the loading looks okay, and the Live Property Explorer shows everything as if it were loaded correctly.

If the above-mentioned code is part of a more complex application (with multiple pages and navigation between them), the error occurs earlier.

The error occurs in my development environment with Windows 10, as well as at the customer's site with Windows 11.

Expected behavior

I have tried other methods of loading the image, changing the binding, caching the BitmapImage, and none of them helped.

Screenshots

No response

NuGet package version

None

Windows version

No response

Additional context

No response

@usdarmy usdarmy added the bug Something isn't working label Feb 16, 2024
@microsoft-github-policy-service microsoft-github-policy-service bot added the needs-triage Issue needs to be triaged by the area owners label Feb 16, 2024
@kmgallahan
Copy link
Contributor

I can't repro in your sample app. Note from the BitmapSource.SetSourceAsync docs:

In low memory situations (most likely on lower-memory phones), it is possible for an exception to be raised with the message "The image is unrecognized" and an HRESULT of 0x88982F60. While this exception ordinarily indicates bad data, if your app is close to its memory limit then the cause of the exception is likely to be low memory. In that case, we recommend that you free memory and try again.

You may want to turn on mixed mode debugging if not already on to observe native exceptions

@usdarmy
Copy link
Author

usdarmy commented Feb 19, 2024

You may want to turn on mixed mode debugging if not already on to observe native exceptions

I have mixed mode debugging enabled and no exceptions are thrown. Instead, a blank screen appears and the application continues to respond and display another image. Sometimes it fails to display two consecutive images. In my case, the error manifests itself after about a minute and a half of intensive clicking. After that, it happens more often - every fifth image load, for example.

@usdarmy
Copy link
Author

usdarmy commented Feb 19, 2024

I am addressing the problem concurrently on Stack Overflow, and I received an interesting answer suggesting the use of RelayCommand. According to initial findings, it seems that the error does not occur afterward. Is it possible that the RelayCommand handler runs on a different thread than the PointerPressed handler, as it appears in my code? The issue with threads is also indicated by the fact that the error occurs randomly.
Here is the modified code with RelayCommand.

@kmgallahan
Copy link
Contributor

kmgallahan commented Feb 19, 2024

Is it possible that the RelayCommand handler runs on a different thread than the PointerPressed handler, as it appears in my code?

No.

There are two major differences in the implementations:

  1. Using synchronous commands to handle input vs. using async event handlers with multiple awaits, allowing multiple handlers to be running at the same time. The 3 awaits are 3 different continuations returning to the UI thread.
  2. Reading & decoding an image from disk every time vs. using a static path that the Image control caches.

You could rule out 1 as the problem by simply using a bool to return at the start of the event handler if it is already running:

private static async Task<BitmapImage> GetImageSourceFromAssets(string path)
{
  if(isRunning) return;
  
  isRunning = true;

  ...

  isRunning = false;
}

@usdarmy
Copy link
Author

usdarmy commented Feb 21, 2024

I tried to modify the application according to all the advice - avoiding loading from the stream, using ObservableProperty, using RelayCommand, and the error still persists. However, only in my virtualized DEV environment and on one of the customer's two computers. I have come to the conclusion that the issue lies in the environment, not in the application itself. Thank you for your support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants