c - 从另一个线程更新 Gtk+2 TextView 小部件

标签 c multithreading user-interface gtk gtk2

我正在用 GTK 编写一个聊天客户端。客户端具有主 GTK 循环,以及一个生成的线程,该线程位于并阻塞在 read() 函数处,等待来自连接到套接字的文件描述符的输入。

一旦读取函数通过阻塞,它就会有一个文本字符缓冲区,我想将其附加到 GTK TextView 小部件,但是,这是在与主 GTK 循环不同的线程中。

如何才能最快地从其他线程更新 GUI?在 Java 中,我会使用 SwingUtilities.invokeLater(new Runnable()) 方法来从主线程调用该方法。我希望在 C 中实现类似的行为并使用 GTK。

这是从新线程调用的函数...

void* messageReceived(void* data)
{
    struct ClientWindow* localVar = (struct ClientWindow*)data;

    while(TRUE)
    {
        char buf[256];
        int bytesRead = read(localVar->socketFileDescriptor, buf, 256);
        GtkTextBuffer* tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(localVar->chatHistoryTextView));

        GtkTextIter end;

        //This code needs to execute in the main thread
        gtk_text_buffer_get_end_iter(tb, &end);
        gtk_text_buffer_insert(tb, &end, buf, -1);

    }
}

最佳答案

我想出的解决方案是使用g_idle_add()函数。我不知道我是否遗漏了一些东西,因为解决方案很简单,但没有人识别它,所以这让我有点担心。

void* messageReceived(void* data)
{
    struct ClientWindow* localVar = (struct ClientWindow*)data;
    char* message = NULL;
    int bytesRead = 0;
    do
    {

        message = bufferedRead(localVar->socketFileDescriptor, 4, &bytesRead);


        struct UpdateGUIMessage* updateGui = malloc(sizeof(struct UpdateGUIMessage));
        memset(updateGui, 0, sizeof(struct UpdateGUIMessage));

        updateGui->clientWindow = localVar;
        updateGui->message = message;
        updateGui->bytesRead = bytesRead;

        g_idle_add(G_SOURCE_FUNC(updateGUI), updateGui);

    }while(message != NULL);
}



bool updateGUI(void* data)
{
    struct UpdateGUIMessage* localVar = (struct UpdateGUIMessage*)data;

    GtkTextBuffer* tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(localVar->clientWindow->chatHistoryTextView));

    GtkTextIter end;

    gtk_text_buffer_get_end_iter(tb, &end);
    gtk_text_buffer_insert(tb, &end, localVar->message, localVar->bytesRead);

    free(localVar->message);
    free(data);

    return FALSE;       //So it only gets called once and then is removed
}

关于c - 从另一个线程更新 Gtk+2 TextView 小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55831411/

相关文章:

Jelly Bean 中的 Android 面板样式(Card UI)是否可用?

python - 使 Tkinter 窗口成为非 Tkinter 窗口的子窗口

java - 我如何决定使用哪个库来创建 UI?

java - 如果我自己调用 run() 方法会发生什么?

c - 套接字在终止后写入程序 (C)

c - 为 C 打印扩展 ASCII 字符的好方法是什么?

c - 库调用 localtime() 在不同 Linux 平台上的行为

c - & 和 * 运算符使我的 fread() 在 C 中成功

C 中的交叉编译器二进制兼容性

c++ - 这是启动和停止线程的安全方法吗?