运维开发网

在Gtk 2.0应用程序中使用pthreads的安全性

运维开发网 https://www.qedev.com 2020-07-13 21:24 出处:网络 作者:运维开发网整理
我有一个简单的多线程Gtk 2.0应用程序,它从多个来源(麦克风,网络摄像头,温度传感器)获取数据,并将这些数据显示为屏幕上的图像(网络摄像头帧抓取,麦克风数据表示为示波器渲染,文本等). 根据我对Gtk手册and various articles的理解,只有主处理线程应该使用影响UI的任何Gtk函数/调用.但是,main()入口点在gtk_main()上阻塞,直到我关闭UI.除了映射到我在UI中
我有一个简单的多线程Gtk 2.0应用程序,它从多个来源(麦克风,网络摄像头,温度传感器)获取数据,并将这些数据显示为屏幕上的图像(网络摄像头帧抓取,麦克风数据表示为示波器渲染,文本等).

根据我对Gtk手册and various articles的理解,只有主处理线程应该使用影响UI的任何Gtk函数/调用.但是,main()入口点在gtk_main()上阻塞,直到我关闭UI.除了映射到我在UI中单击按钮或滑块之类的事件处理程序之外,似乎唯一的选择是产生一些pthread并让他们定期对数据进行采样并更新UI中的屏幕信息.

我记得做了一些MFC GUI开发很长一段时间,应用了类似的原则:只有一个特定的线程应该更新UI元素.如何在C中使用Gtk 2.0实现这一目标?

谢谢.

根据 documentation,主even循环可以接受来自不同线程的源:

A GMainContext can only be running in a single thread, but sources can

be added to it and removed from it from other threads.

因此,您可以通过以下方式在工作线程的UI线程中注入代码:

>创建GSource(例如,使用g_idle_source_new);

>使用g-source-set-callback添加要执行的代码;

>使用g_source_attach()将其附加到UI线程上下文.

以下是GTK 2和GLib> = 2.32的示例程序:

#include <gtk/gtk.h>

#define N_THREADS    100
#define N_ITERATIONS 100

GtkWidget *bar;
GMainContext *context;

static gboolean
update_progress_bar(gpointer user_data)
{
    gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(bar),
                                  g_random_double_range(0, 1));
    return G_SOURCE_REMOVE;
}


static gpointer
thread_func(gpointer user_data)
{
    int n_thread = GPOINTER_TO_INT(user_data);
    int n;
    GSource *source;

    g_print("Starting thread %d\n", n_thread);

    for (n = 0; n < N_ITERATIONS; ++n) {
        /* If you want to see anything you should add a delay
         * to let the main loop update the UI, e.g.:
         * g_usleep(g_random_int_range(1234, 567890));
         */
        source = g_idle_source_new();
        g_source_set_callback(source, update_progress_bar, NULL, NULL);
        g_source_attach(source, context);
        g_source_unref(source);
    }

    g_print("Ending thread %d\n", n_thread);
    return NULL;
}


gint
main(gint argc, gchar *argv[])
{
    GtkWidget *window;
    GThread *thread[N_THREADS];
    int n;

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    bar = gtk_progress_bar_new();
    gtk_container_add(GTK_CONTAINER(window), bar);

    context = g_main_context_default();

    for (n = 0; n < N_THREADS; ++n)
        thread[n] = g_thread_new(NULL, thread_func, GINT_TO_POINTER(n));

    gtk_widget_show_all(window);
    gtk_main();

    for (n = 0; n < N_THREADS; ++n)
        g_thread_join(thread[n]);

    return 0;
}

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号