Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Creation of object in thread not accessible
Message
From
01/06/2011 11:15:04
Timothy Bryan
Sharpline Consultants
Conroe, Texas, United States
 
 
General information
Forum:
ASP.NET
Category:
Coding, syntax and commands
Environment versions
Environment:
C# 4.0
OS:
Windows XP SP2
Miscellaneous
Thread ID:
01512341
Message ID:
01512440
Views:
47
>>>>Hi all,
>>>>
>>>>I have been moving some code to run in a background thread to speed up the performance. In my background worker I create the Configuration class which contains this property.
>>>>
>>>>
>>>>/// <summary>
>>>>/// Main Window State Setting
>>>>/// </summary>
>>>>public System.Windows.WindowState MainWindowState
>>>>{
>>>>	get { return OCSDApplication.Current.MainWindow.WindowState; }
>>>>	set { OCSDApplication.Current.MainWindow.WindowState = value; }
>>>>}
>>>>
>>>>
>>>>Later when Application.InitializeComponent is run, this fails because of "InvalidOperationException" - "The calling thread cannot access this object because a different thread owns it".
>>>>
>>>>Is there a way when it is created to get the ownership of the class back on the main thread? This is WPF by the way.
>>>
>>>Dispatcher ? This works and maybe you can adapt:
   public partial class SomeWindow : Window
>>>    {
>>>        public SomeWindow()
>>>        {
>>>            InitializeComponent();
>>>
>>>            BackgroundWorker b = new BackgroundWorker();
>>>            b.DoWork += new DoWorkEventHandler(DoWork);
>>>            b.RunWorkerAsync();
>>>        }
>>>
>>>        public void SetMainWindowState(WindowState ws)
>>>        {
>>>            Application.Current.MainWindow.WindowState = ws;
>>>        }
>>>
>>>        public WindowState GetMainWindowState()
>>>        {
>>>            return Application.Current.MainWindow.WindowState;
>>>        }
>>>
>>>        void DoWork(object sender, DoWorkEventArgs e)
>>>        {
>>>            MainWindowState = WindowState.Maximized;
>>>            WindowState test = MainWindowState;
>>>        }
>>>
>>>        private WindowState mainWindowState;
>>>        public WindowState MainWindowState
>>>        {
>>>            set { Dispatcher.Invoke(DispatcherPriority.Normal, new Action<WindowState>(SetMainWindowState), value); }
>>>            get
>>>            {
>>>                Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate()
>>>                    { mainWindowState = this.GetMainWindowState(); }));
>>>                return mainWindowState;
>>>            }
>>>        }
>>>    }
>>
>>In this case Dispatcher is Application.Dispatcher?
>
>No, in the example it's the SomeWindow.Dispatcher. I guess you could do the same thing using Application.Dispatcher.
>
>>In my configuration class would it not have to be System.Windows.Threading.Dispatcher? Would this make a difference?
>
>System.Windows.Threading.Dispatcher is the class returned by DispatcherObject.Dispatcher.
>AFAICS, if you use the static Threading.Dispatcher.CurrentDispatcher property it will only give you the dispatcher for the current thread - which won't be much use.....
>
>Sorry, hard for me to try to explain this without it sounding confusing :-{


I am very baffled as to how to solve this issue. Here are more details and would love to get some ideas on how to figure this out.

The Configuration class is just properties that store configuration that is saved. I have the reference to this class in a static property of a global object and lazy load this class in the property. There is an initialization on the class that occurs in a background worker and I suspect that is what may be causing the problem. The configuration gets lazy loaded and the initialization occurs just fine. But later when the Application.Run occurs, there is some access to these properties that cause a Invalid Operation Exception because it is not owned by that thread. I have attached a snapshot that appears as though the property is owned by a worker thread.

Here is the property that holds this reference.
public static OCSDConfiguration AppConfigurationMgr
{
	get
	{
		if (_appConfigurationMgr == null)
			_appConfigurationMgr = Factory.CreateConfigurationManager();
		return _appConfigurationMgr;
	}
	set { _appConfigurationMgr = value; }
}
private static OCSDConfiguration _appConfigurationMgr;
Here is the initialize method that gets called from a background worker. I thought background workers were a bit more savy about handling cross thread synchronization. I assume this is the thread that is claiming to own those properties because of this.
internal void Initialize()
{
    var loadedConfig = (OCSDConfiguration)OCSDAppMain.DBUserSettings.GetValue(DBConsts.SETTING_CLIENTCONFIGURATION, "", typeof(OCSDConfiguration));
    if (loadedConfig != null)
    {
        OCSDMisc.Assign(this, loadedConfig);
    }
}
When searching for uses of the MainWindowState I find none. When I do a search for MainWindowState I don't find anything that is touching the setter or getter of the property. I assume then it is in xaml somewhere and have not found it. Regardless of that however it does get touched and must be the UI thread which is touching it. There are other properties in here that will be the same problem, this just happens to be the first to stop it.

How do I initialize this class in a background worker but get the ownership of the properties back on the UI so they can be touched by the UI thread?

Thanks
Timothy
Timothy Bryan
Previous
Reply
Map
View

Click here to load this message in the networking platform