在我的应用程序中,我正在任务中打开图像数据。但是,当我试图在与创建图像相同的函数中的while循环中从BitmapSource的BitmapSource请求一个属性时,出现以下错误:
The calling thread cannot access this object because a different thread owns it
但是当我在while循环之前调用属性时,它可以正常工作。就我所知,这是在同一函数中,这应该全部是同一线程吗?那么为什么我会收到错误消息?
给出错误的代码:
public AnalogInputs()
{
Task.Run(() =>
{
AnalogInputsSimulationTask();
});
}
private async void AnalogInputsSimulationTask()
{
BitmapSource bSource = new BitmapImage(new Uri("pack://application:,,,/Images/HBT_Light_Diode_Simulation.bmp"));
while (true)
{
var bytesPerPixel = (bSource.Format.BitsPerPixel + 7) / 8; //This line gives the error
await Task.Delay(1);
}
}
但是当我像这样格式化AnalogInputsSimulationTask函数时,不会出现错误:
private async void AnalogInputsSimulationTask()
{
BitmapSource bSource = new BitmapImage(new Uri("pack://application:,,,/Images/HBT_Light_Diode_Simulation.bmp"));
var bytesPerPixel = (bSource.Format.BitsPerPixel + 7) / 8; //Now there is no error
while (true)
{
await Task.Delay(1);
}
}
因为这是我的问题的精简版本,所以我需要第一种格式才能工作,我想加载一次图像,然后在while循环中对其进行处理。但是我无法在while循环中访问它。
我知道当您尝试从Task中访问GUI内容时通常会出现此错误,但是我现在正在Task中执行所有操作,并且该图像未在GUI中的任何位置显示或使用。
答案 0 :(得分:1)
任务是棘手的野兽。如果您等待来自GUI线程的Task.Delay,则在延迟之后您将返回GUI线程,因为继续操作是使用启动任务的代码的同步上下文调用的,并且GUI线程的同步上下文在GUI线程。当您调用Task.Run时,您现在处于线程池线程(或长时间运行的专用线程)中。当前的任务调度程序不受同步上下文的支持,它将在线程池线程(通常,但不一定是另一个线程)中调用。
在您的代码中,在Task.Run命中的第一个线程池线程中创建了BitmapSource。因此,只能从该线程访问它。当您等待Delay时,继续进行到另一个线程池线程(而不是BitmapSource的线程/所有者)。如果没有Task.Run(最初跳转到新线程),此代码将无法正常运行。