tags:

views:

46

answers:

2

Hi,

I have recently implemented a scrolling text across an area of limited screen estate using a timers repeating every 100ms, and some simple string appending.

However, after this very implementation, I have come to realise that my GUI is getting randomly bugged/corrupted after a certain while. That is to say that some widgets/windows become completely white, and eventually the entire GUI turns white and unclickable.

What is weird is that there is no error debug output at all.

Having said that, I am using Mono with GTK-Sharp for the application. Does anyone have an idea or a possible clue how and why this is happening?

If not, how can I further debug this properly?

Thanks, really appreciate it.

PS: Sometimes, it takes up to 1.5 hours for the thing to start corrupting, it has random timeframes for it to start happening.

This is my the code implemented that caused this issue:

void ScrollSyncTo(object sender, System.Timers.ElapsedEventArgs e)
{
    //initial check if it fits nicely alr
    if (sync_to_full_txt.Length <= sync_to_max_char)
    {
        sync_to_timer.Stop();
        return;
    }

    //check for pause
    if (sync_to_pause >= 0)
    {
        sync_to_pause--;
        return;
    }

    //check direction
    int temp_psn;
    string temp_str;
    if (sync_to_direction)
    {
        temp_psn = sync_to_posn + 1;
        if (sync_to_full_txt.Substring(temp_psn).Length < sync_to_max_char)
        {
            sync_to_pause = sync_to_break_steps;
            sync_to_direction = false;
            sync_to_posn = sync_to_full_txt.Length - 1;
            System.GC.Collect();
            return;
        }
        else
        {
            temp_str = sync_to_full_txt.Substring(temp_psn, sync_to_max_char);
        }
    }
    else
    {
        temp_psn = sync_to_posn - 1;
        if (temp_psn + 1 < sync_to_max_char)
        {
            sync_to_pause = sync_to_break_steps;
            sync_to_direction = true;
            sync_to_posn = 0;
            System.GC.Collect();
            return;
        }
        else
        {
            temp_str = sync_to_full_txt.Substring(temp_psn - sync_to_max_char + 1, sync_to_max_char);
        }
    }

    //lets move it
    sync_to.Text = temp_str;
    sync_to_posn = temp_psn;
}
+1  A: 

To program in GTK with multiple threads, you have to do a couple things to make your program thread-safe. Here is short explanation using C.

I'm more familiar with GTK in C, but I'm assuming it works the same in GTK#. So you have to call GLib.Thread.Init() and Gdk.Threads.Init() at the beginning of your program, bracket your call to Application.Run() with Gdk.Threads.Enter() and Gdk.Threads.Leave(), and also make sure any GTK and GDK calls in background threads (not GTK signal handlers) are between Gdk.Threads.Enter() and Gdk.Threads.Leave().

ptomato
A: 

System.Timers.Timer callbacks come from a threadpool thread, but GTK objects can only safely be accessed from the GTK thread. I would suggest using GLib.Timeout, which runs on the GTK thread.

mhutch
It's a common myth that GTK objects can only be accessed from the GTK thread, but it's not true. They can be accessed from any thread as long as you obtain the GTK lock with `Gdk.Threads.Enter()`.
ptomato
Also, there's no guarantee that `GLib.Timeout` runs on the GTK thread. In fact, it probably doesn't, but your timeout callback is guaranteed to hold the GTK lock.
ptomato
Not true. If you call GLib.Timout.Add in a GTK app, the timeout runs in the GTK mainloop context. Also, Gdk.Threads.Enter has problems when using GTK# with .NET on Windows, and can block the GTK mainloop if misused, which is why I don't tend to advise its use, especially when threads are entirely unnecessary, as in the case of the original question.
mhutch