将 BitmapSource 发送到任务进行计算 - wpf c#

Send BitmapSource to task for calculation - wpf c#

我的程序中有两个图像,我有一个比较两个 BitmapSource 的函数,问题是我将 ImageSource 转换为 BitmapSource 并将其分配给一个变量,然后将它发送到任务中的函数(因为该功能相当慢,我更喜欢使用任务,然后在完成后更新用户),它给了我一个错误,任务不能使用这个变量,因为另一个线程拥有它......请帮我修复它。

private async void btnAnalyze_Click(object sender, RoutedEventArgs e)
    {
        if (AnalyzeImage?.Status == TaskStatus.Running) await AnalyzeImage;
        var baseSource = (BitmapSource)imgBase.Source;
        var newSource = (BitmapSource)imgNew.Source;
        if (baseSource?.CompareSizeTo(newSource) == false)
        {
            ShowStatus("Images are different in size or at least one of them is null");
            return;
        }
        btnAnalyze.IsEnabled = false;
        ShowStatus();
        try
        {
            AnalyzeImage = Task<BitmapSource>.Factory.StartNew(() => baseSource?.ConvertToBitmap().CompareTo(newSource?.ConvertToBitmap()).BitmapToImageSource());
            InvokeA(() => waitingPanel.Visibility = Visibility.Visible);
            await AnalyzeImage;
            imgNew.Source = AnalyzeImage.Result;
        }
        catch (Exception ex) { Notify("Error in btnAnalyzeClick", ex, true); }
        finally { InvokeA(() => waitingPanel.Visibility = Visibility.Hidden); }
    }

DispatcherObject 派生的对象具有 线程关联性 ,即一旦创建,它们就由调用线程 "owned"。在 WPF 应用程序中,它通常是 UI 线程。

如果 BimtapSource 实例化放在 await 之后,它将使用当前上下文(在本例中为 UI),这使得 UI 可以使用该对象组件:

private async void btnAnalyze_Click(object sender, RoutedEventArgs e)
{
    if (AnalyzeImage?.Status == TaskStatus.Running) await AnalyzeImage;
    var baseSource = (BitmapSource)imgBase.Source;
    var newSource = (BitmapSource)imgNew.Source;
    if (baseSource?.CompareSizeTo(newSource) == false)
    {
        ShowStatus("Images are different in size or at least one of them is null");
        return;
    }
    btnAnalyze.IsEnabled = false;
    ShowStatus();
    try
    {
       waitingPanel.Visibility = Visibility.Visible;
       var worker = Task<Bitmap>.Factory.StartNew(() =>        
                      baseSource?.ConvertToBitmap()
                     .CompareTo(newSource?.ConvertToBitmap()));

        var bmp = await worker;

        // The next statement is executed in UI synchronization context
        imageNew.Source = bmp.BitmapToImageSource(); 

    }
    catch (Exception ex) 
    { 
       Notify("Error in btnAnalyzeClick", ex, true); 
    }
    finally 
    { 
       waitingPanel.Visibility = Visibility.Hidden;
    }
 }