WPF呈现线程失败异常

wdebmtf2  于 2023-05-19  发布在  其他
关注(0)|答案(2)|浏览(294)

在我的应用程序中,我有一个在后台运行的任务来执行一个长时间运行的作业。用户可以通过单击“停止”按钮随时取消作业。具体实现如下:

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);
}

问题:有时,在执行作业时,GUI停止更新(挂起)。如果我尝试操作GUI,会发生异常:System.Runtime.InteropServices.COMException:UCEERR_RENDERTHREADFAILURE(HRESULT异常:0x88980406)
我在这里发现了一个类似的问题:WPF render thread failures
你知道这是什么以及如何解决这个问题吗?我的源代码有什么问题吗?

gudnpqoy

gudnpqoy1#

我不知道你为什么会犯这个错误。但是,您可以尝试这样的实现:

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;
}
flvlnr44

flvlnr442#

在将大型WPF应用程序从.NET Framework迁移到.NET 7之后,对于某些用户,应用程序开始崩溃,并出现此异常。

System.Runtime.InteropServices.COMException UCEERR_RENDERTHREADFAILURE (0x88980406)

异常的原因尚不清楚,但禁用硬件图形加速对我来说是有效的。

using System.Windows.Media;

RenderOptions.ProcessRenderMode = System.Windows.Interop.RenderMode.SoftwareOnly;

P.S.有关此异常的讨论,请参见document from Microsoft

相关问题