Help me with threads.

B

Bruno Jouhier [MVP]

Jon Skeet said:
Just to correct something - Swing and AWT (and possibly SWT as well,
not sure) also require you to only access UI objects in the UI thread.
That's what SwingUtilities.invokeLater/invokeAndWait are for.

Then, they have changed things since I used these toolkits. I worked with
the first releases (AWT in 96-98, just a little bit of Swing, no SWT but I
assumed it was the same) and there was no such thing at the time (but lots
of ugly deadlocks in AWT). They probably had to go this way to be able to
take advantage of the fast MFC controls when running on Windows, and to get
rid of their awful deadlocks.

Bruno
 
W

Willy Denoyette [MVP]

This is not correct, Windows.Forms is built on top of Windows and has
nothing to do with COM apartments , unless your controls are activeX
controls, in which case they are apartment threaded so must be accessed only
from that thread that created the control.
The fact that you should only access UI elements from the thread that
created them is because "Window Handles" (HWND) have thread affinity.
Note that this also applies to other toolkits, everything that runs on
windows has to respect that simple rule "use your 'Window handles' only from
the thread that created them".

Willy.
 
J

Jon Skeet [C# MVP]

Bruno Jouhier said:
Then, they have changed things since I used these toolkits. I worked with
the first releases (AWT in 96-98, just a little bit of Swing, no SWT but I
assumed it was the same) and there was no such thing at the time (but lots
of ugly deadlocks in AWT). They probably had to go this way to be able to
take advantage of the fast MFC controls when running on Windows, and to get
rid of their awful deadlocks.

Swing has always been the same, as far as I'm aware. I'm not sure about
AWT, but I doubt that they'd make such a breaking change late on. It
may well not have been well documented, of course...
 
B

Bruno Jouhier [MVP]

Jon Skeet said:
Swing has always been the same, as far as I'm aware. I'm not sure about
AWT, but I doubt that they'd make such a breaking change late on. It
may well not have been well documented, of course...

I looked a bit more into this:

Swing and SWT are not free-threaded (except for some very specific calls in
the Swing toolkit). So, you have to go through the invoke calls if you are
calling from another thread. And I was completely wrong on those (I
extrapolated too quickly from my early AWT experience).

AWT sounds more complex: internally, there is a single thread that accesses
the message queue and the drawing methods, but externally, you are allowed
to call the AWT methods from several threads. This leads to extra complexity
and inefficiencies in the toolkit, which is why a different approach was
taken by Swing and SWT. So, from what I've found on Google (which is not
always very clear), it seems that AWT is still free threaded from the
outside, even if it is single threaded inside.

Actually, it would not be too difficult to turn the WinForms toolkit into a
free threaded toolkit "from the outside", you would just need to rewrite
every public API entry point as:

foo()
{
if (InvokeRequired)
BeginInvoke(new FooDelegate(internalFoo));
else
internalFoo();
}

The toolkit would then be free threaded "from the outside" but it would be
slower.

Bruno.
 
J

Jeff Louie

Bruno... Sorry about the late reply, but I think my brain just was
overloaded
with too much new stuff :). I really appreciate your looking at my code
and
finding such a fundamental error. I have updated the code at my site,
but still
working things out in my head.

Regards,
Jeff
I looked quickly at your example, and I see a potential problem with
your
"callback" method: this method is called from your thread
(ThreadedProcess)
and it interacts with the GUI (it appends text to the textBoxControls).
 
J

Jeff Louie

Jason... Thanks for the great post. I was able to just follow your
example and
redesign my little class using events and delegates and I updated the
code on
my website. Honestly, I have not yet gotten my head completely around
how
delegates and events work especially concerning when the auto generated
class that "encapsulates a type safe function is called," but I expect
it will
come to me eventually.

Regards,
Jeff
What you need to do is to define an event that your worker thread can
throw
when it needs to send data back to the UI thread, create an event
handler to
process that event, and in the event handler do a little bit of work to
make
sure that you're in the correct thread before you update your UI
controls.<
 
M

Marcos Stefanakopolus

I'll be the first to admit that it took me a while to get my head around it
too. Mostly, I think, the difficulty is not with the concepts themselves
but with the layers of C# semantic and syntactic glue that you need to lay
down in order to make your application compile and be correct. In
particular, the need to go to such extensive trouble just to define an event
that passes data back to its handlers seems unduly burdensome. This is
something that I am hopeful a future version of C# and Visual Studio will
make easier (for example, if the compiler could infer the delegate
declaration for you, and if the IDE could write the EventArgs class
declaration for you, that would be enormously helpful). Of course, not
being on the teams that work on those things myself, I cannot say one way or
the other whether such features are on anybody's to-do list...
 
J

Jeff Louie

Marcos... Well, I am only now getting a bit comfortable with my
callback. I finally figure that the callback:

public void StartInThread(ThreadedProcessEventHandler callhome){
...
callhome(this,new
ThreadedProcessEventArgs(this.ConsoleOutput,this.ConsoleError,this.ExitC
ode));
}

must be "expanded" by the compiler to

Delegate[] handlers= callhome.GetInvocationList();
foreach (Delegate d in handlers)
{
d.DynamicInvoke(new object[]{this,
new
ThreadedProcessEventArgs(this.ConsoleOutput,this.ConsoleError,this.ExitC
ode)});
}

Regards,
Jeff
I'll be the first to admit that it took me a while to get my head
around it too. Mostly, I think, the difficulty is not with the concepts
themselves but with the layers of C# semantic and syntactic glue that
you need to lay down in order to make your application compile and be
correct.<
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top