Thread-Safe GUI-programming

G

Guest

Hey there,

im quite new to C# GUI-Framework and got a question now. In Java its no
problem todo cross-over Thread-calls. So i can change something in a Window
from another thread. It seems C# lacks of this ability.

I got a normal GUI and want to start a thread where this gui is also changes
from. I made this working before with delegates. Ok so far...this would be a
way to solve the issue. But it looks like much work if i have todo this for
every single method i want to use over different threads.

No heres my question now...could you tell me whats the best practice in this
case ? How do you implement that ?


Thanks and regards,
oliver
 
J

Jon Skeet [C# MVP]

im quite new to C# GUI-Framework and got a question now. In Java its no
problem todo cross-over Thread-calls. So i can change something in a Window
from another thread.

No, you can't (at least not in Swing/AWT). It may work in some cases,
but it's not guaranteed to and you shouldn't do it. That's the whole
point of SwingWorker. From the docs for SwingWorker:

<quote>
Swing components should be accessed on the Event Dispatch Thread only.
It seems C# lacks of this ability.

Just to be clear, it's not a language issue. It's a library issue -
and the Java libraries (well, Swing/AWT at least) have exactly the
same issue. Most UI libraries take exactly the same approach, as far
as I'm aware.
I got a normal GUI and want to start a thread where this gui is also changes
from. I made this working before with delegates. Ok so far...this would be a
way to solve the issue. But it looks like much work if i have todo this for
every single method i want to use over different threads.

No heres my question now...could you tell me whats the best practice in this
case ? How do you implement that ?

Invoke/BeginInvoke are indeed the way to go. Try to minimise the
number of "entry points" to the UI,
and make each of those thread-safe.

Jon
 
S

Scott Gifford

[...]
I got a normal GUI and want to start a thread where this gui is also changes
from. I made this working before with delegates. Ok so far...this would be a
way to solve the issue. But it looks like much work if i have todo this for
every single method i want to use over different threads.

No heres my question now...could you tell me whats the best practice in this
case ? How do you implement that ?

Oliver -

I've recently started using C#'s anonymous methods for this:

public void ThreadUpdateStatus(string s)
{
try
{
this.Invoke(new EventHandler(delegate(object sender2, EventArgs e2)
{
lblStatus.Text = s;
}));
}
catch (ObjectDisposedException)
{
// Do nothing
}
}

I like this approach because it avoids creating a separate method for
every action you want to take from a thread, and keeps the code all in
one place, which makes it easier to quickly tell what's going on.

Good luck!

----Scott.
 
A

Arnshea

Hey there,

im quite new to C# GUI-Framework and got a question now. In Java its no
problem todo cross-over Thread-calls. So i can change something in a Window
from another thread. It seems C# lacks of this ability.

I got a normal GUI and want to start a thread where this gui is also changes
from. I made this working before with delegates. Ok so far...this would be a
way to solve the issue. But it looks like much work if i have todo this for
every single method i want to use over different threads.

No heres my question now...could you tell me whats the best practice in this
case ? How do you implement that ?

Thanks and regards,
oliver

For the .net 1.1 framework (e.g., no anonymous methods) I've been
using the following pattern:

void ChangeWidget()
{
if ( InvokeRequired )
Invoke(new MethodInvoker(ChangeWidget))
else
// ... manipulate UI
}

To pass parameters you'll need a matching delegate (and the Invoke
overload that accepts an object[]).
 
O

Oliver

Hey Scott,
I've recently started using C#'s anonymous methods for this:

public void ThreadUpdateStatus(string s)
{
try
{
this.Invoke(new EventHandler(delegate(object sender2,
EventArgs e2)
{
lblStatus.Text = s;
}));
}
catch (ObjectDisposedException)
{
// Do nothing
}
}

I like this approach because it avoids creating a separate method for
every action you want to take from a thread, and keeps the code all in
one place, which makes it easier to quickly tell what's going on.


yeah that looks like a cleaner solution. But the main-problem still exists.
I have to write new methods or override existing ones of methods i'd like to
use.

Well but i see now its not just me doing it wrong or something so i can live
with that.


thanks guys!
oliver
 
O

Oliver

Hey Jon,
No, you can't (at least not in Swing/AWT). It may work in some cases,
but it's not guaranteed to and you shouldn't do it. That's the whole
point of SwingWorker. From the docs for SwingWorker:

<quote>
Swing components should be accessed on the Event Dispatch Thread only.
</quote>

yeah true. And i more meant that i dont need such thing like a
delegate/invoke stub which i have to write on my own. It can become much
work especially if you wrote your application non-thread-aware and got to
bring thread-awareness into it on a later time :/

Well but you answered my main-question which referred to the way of dealing
itself.


So thanks jon and regards,
oliver
 
J

John B

Scott said:
[...]
I got a normal GUI and want to start a thread where this gui is also changes
from. I made this working before with delegates. Ok so far...this would be a
way to solve the issue. But it looks like much work if i have todo this for
every single method i want to use over different threads.

No heres my question now...could you tell me whats the best practice in this
case ? How do you implement that ?

Oliver -

I've recently started using C#'s anonymous methods for this:

public void ThreadUpdateStatus(string s)
{
try
{
this.Invoke(new EventHandler(delegate(object sender2, EventArgs e2)
{
lblStatus.Text = s;
}));

I too favour this paradigm but instead use the MethodInvoker Delegate.

this.[Begin]Invoke(new MethodInvoker(delegate{
//Do some stuff
}));

<...>
JB
 
J

Jon Harrop

Jon said:
Just to be clear, it's not a language issue.

In a functional language like F#, the overhead is minimal but still there:

form.Invoke(fun () -> button.Text <- "Foo")

Couldn't the language provide a construct to add such indirections across
the interface of a given class, making the given class thread safe?
 
J

Jon Skeet [C# MVP]

Jon Harrop said:
In a functional language like F#, the overhead is minimal but still there:

form.Invoke(fun () -> button.Text <- "Foo")

My point is that the *framework* is still forcing you to marshall the
call to another thread. Yes, F# makes that relatively easy (as does C#
3) but that doesn't make the controls themselves more threadsafe.
Couldn't the language provide a construct to add such indirections across
the interface of a given class, making the given class thread safe?

I certainly wouldn't want *transparent* marshalling of calls to another
thread. Threading is hard enough when everything is explicit - making
marshalling implicit would only make it harder, IMO.
 

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