[Gtk-sharp-list] Thread-safe GUI update

William Garrison gtk at mobydisk.com
Fri Mar 23 20:22:02 EDT 2007


Wouldn't using a regular delegate eliminate this issue?  It would copy 
msg onto the stack for the call so the value wouldn't be overwritten 
during the next loop.  (I'm not sure if this code is quite right, but 
you get the idea)

while (Messages.Count > 0) {
    msg = (Message) Messages.Dequeue();
    send(msg);
    Gtk.Application.Invoke(AppendAValue,msg);
    Thread.Sleep(0);
}

private void AppendAValue(Message msg)
{
    treeStore.AppendAvlues(msg.To, msg.Text);
}

Leon Stringer wrote:
> Michael Hutchinson wrote:
>> On 3/22/07, Leon Stringer <leon.stringer at ntlworld.com> wrote:
>>> Hi,
>>>
>>> I'm updating a list (TreeView with TreeStore) from a thread when
>>> processing some items, something like:
>>>
>>> while (Messages.Count > 0) {
>>>         msg = (Message) Messages.Dequeue();
>>>         send(msg);
>>>
>>>          Gtk.Application.Invoke(delegate {
>>>                 treeStore.AppendAvalues(msg.To, msg.Text);
>>>         });
>>>
>>>         Thread.Sleep(0);
>>> }
>>>
>>> There's another thread adding messages to the message queue.
>>>
>>> The problem is that sometimes the Gtk.Application.Invoke() is executed
>>> after I've dequeued the next message so the wrong item is added to the
>>> list. I could stick a greater value in Thread.Sleep() but this would be
>>> a kludge. Is there any thread-safe way to do this?
>> The problem lies in using an anonymous delegate. The compiler compiles
>> the anonymous delegate to a private method, which gets access to
>> variables in the "parent" method's scope via a private shared object
>> in the parent class. Your code is changing the shared variables before
>> Gtk.Application.Invoke gets fired.
>>
>> However, it may be possible to do it with Gtk.Application.Invoke
>> (object sender, System.EventArgs args, System.EventHandler d).
>>
>> Alternatively you could create a queue object at the class level and
>> put the messages in that. You'd need to lock it (on the SyncRoot
>> property) when you add and remove objects, or you could use the build
>> in sychronisation wrapper to make it thread safe:
>> http://msdn2.microsoft.com/en-gb/library/system.collections.queue.issynchronized.aspx 
> 
> Thanks Michael, that's a fairly comprehensive answer! I'll try adding 
> the second queue and play around with the locking...



More information about the Gtk-sharp-list mailing list