In my application, I have a task which runs in the background to perform a long-running job. The user can cancel the job anytime by clicking Stop button. The implementation is as belows:
private CancellationTokenSource m_tokenSource; private void onStop() { m_tokenSource.Cancel(); } private void onStart() { m_tokenSource = new CancellationTokenSource(); AsyncDoingJob(); } private async void AsyncDoingJob() { await Task.Run(() => { for (int imgIdx = 0; imgIdx < m_ListImageFiles.Count; imgIdx++) { if (m_tokenSource.IsCancellationRequested) // Check if the user clicks Stop button { return; } byte[] imageData = File.ReadAllBytes(m_ListImageFiles[imgIdx]); // Load image in background Application.Current.Dispatcher.Invoke(() => { m_model.Image = CreateImage(imageData); m_model.Image.Freeze(); MyImage = m_model.Image; // This calls NotifyPropertyChanged() to update the image on GUI } // Access to m_model.Image for some reason } }, m_tokenSource.Token); } The problem: Sometimes, while the job is being performed, GUI stop updating (hanging). And if I try to manipulate the GUI, an exception happens: System.Runtime.InteropServices.COMException: UCEERR_RENDERTHREADFAILURE (Exception from HRESULT: 0x88980406)
I found a similar problem reported here: WPF render thread failures
Do you know what it is and how to fix this? Is there anything wrong with my source code?
42 Answers
I can't tell why you get that error. You may however try an implementation like this:
private bool continueLoading; private void OnStop() { continueLoading = false; } private async Task OnStart() { continueLoading = true; await LoadImagesAsync(m_ListImageFiles); } private async Task LoadImagesAsync(IEnumerable<string> imageFiles) { foreach (var imageFile in imageFiles) { if (!continueLoading) { break; } Image = await LoadImageAsync(imageFile); // assignment in UI thread // do more async calls here if necessary } } private static Task<ImageSource> LoadImageAsync(string fileName) { return Task.Run(() => { using (var stream = File.OpenRead(fileName)) { return LoadImage(stream); } }); } private static ImageSource LoadImage(Stream stream) { return BitmapFrame.Create( stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); // Alternative: // // var bitmapImage = new BitmapImage(); // bitmapImage.BeginInit(); // bitmapImage.CacheOption = BitmapCacheOption.OnLoad; // bitmapImage.StreamSource = stream; // bitmapImage.EndInit(); // bitmapImage.Freeze(); // return bitmapImage; } After migrating a large WPF application from the .NET Framework to .NET 7, for some users the application began to crash with this exception.
System.Runtime.InteropServices.COMException UCEERR_RENDERTHREADFAILURE (0x88980406) The reason for the exception is not clear, but disabling hardware graphics acceleration worked for me.
using System.Windows.Media; RenderOptions.ProcessRenderMode = System.Windows.Interop.RenderMode.SoftwareOnly; P.S. See the document from Microsoft for a discussion of this exception.