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