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

时间:2015-08-22 18:16:46

标签: c# wpf bitmap task bitmapimage

我的程序中有两个图像,我有一个比较两个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); }
    }

1 个答案:

答案 0 :(得分:1)

DispatcherObject派生的对象具有线程关联性,即一旦创建,它们就被调用线程“拥有”。在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;
    }
 }