Click here to Skip to main content
15,895,011 members
Please Sign up or sign in to vote.
4.50/5 (2 votes)
See more:
C#
lbTinhTrang.Dispatcher.BeginInvoke ((Action) (() =>; {lbTinhTrang.Content = "str";}), DispatcherPriority.Normal);


with this code no error when you do not change the content for the label but

C#
myGrid.Dispatcher.BeginInvoke ((Action) (() =>; {myGrid.Children.Add (_rec);}), DispatcherPriority.Normal);


Then you see this error

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

as I understand it, I change the label content, it is only one thread creating the label, but with myGrid is due to add a new UI that this UI thread is declared in the socket, it is also myGrid declaration to add another thread should not be.

I search on google but still can not fix, expect him to guide me. I made ​​a small demo with similar errors

I make a demo simlar with error
http://www.mediafire.com/?azv7xhp9rv4v3m9[^]
Posted
Updated 5-Jun-11 1:52am
v2
Comments
Sergey Alexandrovich Kryukov 5-Jun-11 15:22pm    
My 5 for correct issue report. (Few minor complains apply, see my solution.)
--SA

1 solution

You did it all wrong. You need only one Dispatcher and only one call Invoke or BeginInvoke call — in your case, both will work.

What you have done in your code was a big mess: you created a separate invocation queue item for each small call and mixed the two thread. You added several invocations asynchronously using BeginInvoke. In principle it would be possible, but think about it: by BeginInvoke you put two related and competing UI calls to the invocation queue without waiting for the completion of each! In this way, you rely on certain order of completion, which is potentially dangerous!

I've done few modifications of your code. First, I removed a thread declaration form the scope of window instance as you don't use it (you could use BackgroundWorker for this case, but I understand the code is purely experimental, so you may need this class member in real-life code); for this example, I made it a stack variable. I also renamed all auto-generated objects to remind you that you should follow (good) Microsoft naming conventions; I also renamed "rec_" to "rec", to follow naming conventions for stack variables. I removed event handler from XAML to put all code in the window constructor (I also removed all methods you used only once to simplify code and demonstrate the technique using anonymous methods and make the code shorter):

C#
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Threading;

//...

public MainWindow() { //window class constructor
   InitializeComponent();
   buttonThread.Click += (sender, eventArgs) => {
       Thread thread = new Thread(() => {
            gridTest.Dispatcher.Invoke(new Action(() => {
                Rectangle rec = new Rectangle();
                rec.Width = gridTest.Width / 2; //changed to show effect
                rec.Height = gridTest.Height;
                rec.Fill = Brushes.Black;
                rec.HorizontalAlignment = HorizontalAlignment.Left;
                rec.VerticalAlignment = VerticalAlignment.Top;
                gridTest.Children.Add(rec);
            })); //thread body
        }); //buttonThread.Click
        //thread.SetApartmentState(ApartmentState.STA); //no need
        thread.Start();
    }; //buttonThread.Click
} //MainWindow


You should also clean-up your using. With Visual Studio, you can conveniently use context menu "Organize Usings" -> "Remove Unused Usings".

By the way, more complains on how you present your code for review: You should clean it more: remove unused references, remove unused "Resourses" and "Settings.settings", and, more importantly, remove all files which are not in your source code: "*.suo", "*.user", ".\obj\*.*", ".\bin\*.*".

Other then that, I really appreciate the way you present your issue report! Every Inquirer should create some simple sample. You really helped me to fix your code.

For more detail on invocaion, please check my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

For the thread creation, use this convenient technique of thread wrapper:
How to pass ref parameter to the thread[^].

—SA
 
Share this answer
 
v5

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900