Why do I get 'The calling thread must be STA' exception although invoking via Dispatcher?

552 views Asked by At

This method call sits inside a class derived from DispatcherObject:

Dispatcher.Invoke(DispatcherPriority.Input, new ThreadStart(() =>
            {
                var exported = formatProvider.Export(original.Workbook);
                Workbook = formatProvider.Import(exported);
            }));

The method on the class is called by a backgroundworker in its DoWork delegate.

Workbook is Telerik's Workbook, as used by the RadSpreadsheetControl. Obviously, workbooks can only be accessed by the UI thread.

The above code throws an InvalidOperationException, saying

The calling thread must be STA, because many UI components require this.

I don't really understand, as I thought that when invoking the actions with a Dispatcher, I would be calling it from the UI Thread, which is STA?

What am I missing here and how can this be fixed? Or should this work in general and the bug is somewhere else? What could be a reason then?

2

There are 2 answers

3
Jon On BEST ANSWER

TL;DR: You must create this DispatcherObject inside your UI thread, not in a worker.

DispatcherObject.Dispatcher, which you are marshalling the operation to, is set to Dispatcher.CurrentDispatcher at the time of the object's construction. If the object is not created inside your existing UI thread then the documented behavior of CurrentDispatcher is to create a new dispatcher object associated with the thread. Later on, Invoke tries to marshal the call to that thread (which is not STA) resulting in the error.

2
JeffRSon On

It is not sufficient to use a class derived from DispatcherObject. You must use the Dispatcher from an existing UIElement created from XAML (or at least make sure, you create your class from inside the GUI thread where it picks the right Dispatcher).