I\'m very new to threads, so my thoughts and questions might be a bit silly :)
I fill WinForm
control with data from another thread, so I have to call <
This is absolutely wrong:
treeViewWriter.Start();
treeViewWriter.Join();
Never call Thread.Join from Main Thread! because that Join
freezes the application and all those BeginInvoke
/Invoke
never gets fully executed because the message is not handled.
This is how BeginInvoke()
actually works:
Application.DoEvents()
(or the like which is always called in Application.Run()
)BeginInvoke()
WaitHandle
in IAsyncResult
)EndInvoke()
waits for such signal (or if IAsyncResult
from BeginInvoke
is never stored, it gets garbage-collected)So again: you eiter write it purely event-driven or do something like this:
private bool done = false;
void click(object, EventArgs) {
thread.Start();
while(!done) Application.DoEvents();
tree.ExpandAll();
}
ADDON:
Eihter use Invoke()
(synchronized) and the above loop with Application.DoEvents()
or use BeginInvoke() and call your ExpandAll the same way (through BeginInvoke() from the thread)
ADDON2:
private bool done;
void click(object,EventArgs) {
done = false; // init state
new Thread(work).Start(); // start backgound work
while(!done) Application.DoEvents(); // wait until done
finish(); } // finish the job in main thread
void work() {
Thread.Sleep(100); // do your work
done = true; } // signal done
void finish() {
whatever(); } // called on main thread
void click2(object,EventArgs) {
new Thread(work2).Start(); } // just start the hread
void work2() {
Thread.Sleep(100); // do your work
BeginInvoke(new Action(finish)); } // execute finish() on main thread
Create an Action
which Invoke
s the delegate, then BeginInvoke
that action.
This way you will have a callback which you can move the ExpandAll
into:
if (tree.InvokeRequired)
new Action(() => { tree.Invoke(code, tree); }).BeginInvoke((ar) => {
treeDirectoryContents.ExpandAll();
}, null);
else
code.Invoke(tree);
Note that I replaced your original BeginInvoke
with a simple Invoke
.
UPDATE: As firda mentioned correctly, because the main thread is blocked inside the Join
method waiting for the other thread to exit, executing Invoke
on the controls will lead to a deadlock. So now that your ExpandAll
is moved to the callback, you should remove the Join
and everything will be fine.