[MonoDevelop] Issues with the gui thread

Lluis Sanchez lluis@ximian.com
Mon, 20 Sep 2004 23:58:14 +0200


Hi!

One of the problems I find when writing code for MonoDevelop is that the
user interface can only be modified from the GUI thread. This means
that, for example, if I have a background thread that needs to add
something in the task pane, I need to do it through the DispatchService.

However, the fact that TaskService.AddTask (and many other methods)
needs to run in the gui thread is common knowledge not documented
anywhere, and even if it was documented, this information wouldn't be
reliable. For example, the TaskService itself does not modify the user
interface, but an OpenTaskView object is subscribed to the TaskAdded
event, and that one changes de UI. This makes the development of plugins
really hard.

In order to simplify the development and to make MonoDevelop more stable
I think we should stablish a policy like "any public class that can be
used by a plugin must be gui-thread safe" that is, no matter from which
thread a method is called, it should do its work, internally dispatching
the call through the DispatchService if needed.

Following this rule, the TaskService.AddTask method would not need to do
anything special, since it does not directly modify the gui, but
OpenTaskView would need to internally dispatch the TaskAdded event
through the DispatchService.

To simplify even more the development I propose to build two artifacts:

      * Provide a base class for classes that need access to the GUI.
        All method calls to objects of that class would be automatically
        marshalled and executed in the gui thread. This can be
        implemented using ContextBoundObject and the interception sinks
        it provides. This would be really useful for example to make the
        status bar service thread safe by only changing the base class. 

      * Provide a method for building wrapper delegates that would
        automatically marshall calls into the gui thread, so I could do
        something like:

        taskService.TasksChanged +=
        (EventHandler)DispatchService.CreateGuiDispatch (new
        EventHandler (ShowResults));
        
        This would generate a wrapper delegate that would queue the call
        into the gui thread. This would need some Reflection.Emit, but
        not too much.
        
Of course, we could still use the traditional DispatchService methods,
but I think that those "artifacts" would be enough for most of
situations.

Any opinions about this?
Lluis.