1

In my application I'm opening image data in a task. But when I'm tying to request the a property from the BitmapSource inside a while loop in the same function as I created the image I get the following error:

The calling thread cannot access this object because a different thread owns it

But when I call the property before the while loop it works without a problem. This while it is in the same function, as far as my knowledge goes this should all be the same Thread? So why do I get the error?

Code that gives me the error:

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

But when I Format the AnalogInputsSimulationTask Function like this it doesn't give me the error:

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

As this is a very stripped down version of my problem, I need the first format to work, I want to load the image once and then do stuff with it in the while loop. But I cannot access it in the while loop.

I know this error usually comes up when you try to access GUI stuff from within a Task, but I'm now doing everything in the Task and the image isn't shown or used in the GUI anywhere.

8
  • You can only access a U.I. object from the main thread. What is the exact problem that you're trying to solve by using tasks? Commented Oct 24, 2018 at 11:53
  • you can use the debugger to determine which task owns the object in particular Commented Oct 24, 2018 at 11:54
  • @Peregrine The Image isn't really used as a UI item, but it is to simulate value's that are scanned. So in the task every 1 millisecond a new column of the image is read and copied to an array. And this array is used later on in the code. When the image is not used in the UI is it then still a UI interface object? Commented Oct 24, 2018 at 12:02
  • 1
    "You can only access UI objects from the main thread" is not exactly what describes the situation. More precisely DispatcherObjects like BitmapImage have thread affinity, which means they can only be accessed in the thread in which they were created. However, a BitmapImage is also a Freezable, which - if frozen - can be accessed from a thread other than the one in which it was created. Commented Oct 24, 2018 at 12:05
  • 2
    By calling await Task.Delay(1) you release current thread. When 1 ms passes there is no guarantee that the same thread will be selected from thread pool to continue the task. Check value of Thread.CurrentThread.ManagedThreadId Commented Oct 24, 2018 at 12:09

1 Answer 1

1

Tasks are tricky beasts. If you await a Task.Delay from the GUI thread, you'll be back on the GUI thread after the delay because the continuation is invoked using the synchronization context of the code that started the task and the synchronization context for a GUI thread invokes on the GUI thread. When you call Task.Run, you're now in a thread pool thread (or dedicated thread if long-running); the current task scheduler is not backed by a synchronization context and will invoke in a thread pool thread (typically, but not necessarily another thread).

In your code, your BitmapSource is created in the first thread pool thread hit from your Task.Run. It can therefore only be accessed from that thread. When you await the Delay, continuation goes to another thread pool thread (not the thread/owner of the BitmapSource). This code would run fine without the Task.Run (initial jump to a new thread).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.