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):
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Threading;
public MainWindow() {
InitializeComponent();
buttonThread.Click += (sender, eventArgs) => {
Thread thread = new Thread(() => {
gridTest.Dispatcher.Invoke(new Action(() => {
Rectangle rec = new Rectangle();
rec.Width = gridTest.Width / 2;
rec.Height = gridTest.Height;
rec.Fill = Brushes.Black;
rec.HorizontalAlignment = HorizontalAlignment.Left;
rec.VerticalAlignment = VerticalAlignment.Top;
gridTest.Children.Add(rec);
}));
});
thread.Start();
};
}
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