【问题标题】:GLib: g_source_remove() not stopping timeout callbacks on non-default GMainContextGLib:g_source_remove() 不停止非默认 GMainContext 上的超时回调
【发布时间】:2017-12-01 21:10:32
【问题描述】:

我正在使用此函数将超时回调(重复)添加到特定的GMainContext

guint GstThreadHelper::timeoutAdd(guint delay, GSourceFunc function, gpointer data) {
    // See https://developer.gnome.org/programming-guidelines/stable/main-contexts.html.en#implicit-use-of-the-global-default-main-context
    // It is important that all thread functions we invoke don't implicitly decide a maincontext.
    // We must manually provide one.
    GSource *source = NULL;
    guint id;

    source = g_timeout_source_new(delay);
    g_source_set_callback (source, function, data, NULL);
    id = g_source_attach (source, priv->mainContext);
    g_source_unref (source);

    return id;
}

稍后,我使用返回的id 取消回调。

void GstThreadHelper::timeoutRemove(guint id) {
    g_source_remove(id);
}

但是,回调仍然会被调用。这是我的回调。

static gboolean position_update (gpointer user_data)
{
    Player::PrivateData* priv = (Player::PrivateData*)user_data;
    gint64 pos = 0;

    if (gst_element_query_position (priv->playbin, GST_FORMAT_TIME, &pos)) {
        pos = pos / 1000000;
        priv->callback->PositionChanged(pos);
    }

    // Call me again
    return TRUE;
}

我知道我要返回TRUE,但我的理解是它仍然应该停止。如果我通过返回FALSE 来取消回调,我就不会为g_source_remove 调用而烦恼。

为什么g_source_remove 不阻止我的回调被引发?

编辑

如果我用这个替换我的 timeoutAdd 方法...

guint GstThreadHelper::timeoutAdd(guint delay, GSourceFunc function, gpointer data) {
    return g_timeout_add(delay, function, data);
}

...它有效。但是,我不能使用它,因为它不会触发特定 GMainContext 的回调,而不是默认的全局 GMainContext

EDIT2

我将g_timeout_add_seconds_full 的默认源复制到我的函数中,它起作用了。

但是,当我将g_source_attach 更改为使用我的私人GMainContext 时,它失败了。

问题与调用 g_source_remove 以在非默认 GMainContexts 上添加超时有关。

【问题讨论】:

    标签: glib


    【解决方案1】:

    事实证明,g_source_remove 是在您使用全局/默认 GMainContext 的假设下运行的,在这种情况下,我不是。

    我不记得在文档中读过这个。

    无论如何,这是解决方案。

    void GstThreadHelper::timeoutRemove(guint id) {
        GSource* source = g_main_context_find_source_by_id(priv->mainContext, id);
        if (source)
            g_source_destroy (source);
    }
    

    这实际上是g_source_remove 正在做的事情,但使用我们的私人GMainContext

    【讨论】:

    • 你明白了。 g_source_remove() 的文档中提到了这一点:“从默认主上下文中删除具有给定 id 的源。”但我将推动对 GLib 的更改以澄清这一点。使用g_source_destroy()(并传递GSource* 指针,并保留对它的引用;而不是传递guint 标记)是正确的。
    猜你喜欢
    • 2020-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-01
    • 1970-01-01
    • 2011-01-31
    • 2012-06-04
    相关资源
    最近更新 更多