首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 操作系统 >

evolution 施用GAsyncResult实现异步执行的例子

2012-06-26 
evolution 使用GAsyncResult实现异步执行的例子? 下面相关代码主要功能是:在网络连接时,evolution发出准备

evolution 使用GAsyncResult实现异步执行的例子

? 下面相关代码主要功能是:

在网络连接时,evolution发出准备联接信号,前端通知后端evolution-data-server进行长时逻辑,待后端逻辑处理完成后,前端收尾函数被自动调用。

?

? 这段代码主要几个知识点:

1.使用GSimpleAsyncResult进行异步操作。

2.使用g_object_add_toggle_ref进行引用趋势判断。由于前端无法知道evolution-data-server何时处理完成,并且不知道对应object会被多少后端逻辑进行引用。所以需要使用g_object_add_toggle_ref函数,当最后一个引用使用完成后,自动触发相关的收尾操作。

?

前端:

shell/e-shell.c:
static void
shell_prepare_for_online (EShell *shell)
{
??????? /* Are preparations already in progress? */
??????? if (shell->priv->preparing_for_line_change != NULL)
??????????????? return;

??????? shell->priv->preparing_for_line_change = e_activity_new ();

??????? e_activity_set_text (
??????????????? shell->priv->preparing_for_line_change,
??????????????? _("Preparing to go online..."));

?

??????? // 对preparing_for_line_change引用加一

??????? // 并且在对象最后一次被引用(引用计数从n到1)或者最后一次引用后被其他函数引用(引用计数从1到n)时

??????? // 调用回调 shell_ready_for_online

??????? g_object_add_toggle_ref (
??????????????? G_OBJECT (shell->priv->preparing_for_line_change),
??????????????? (GToggleNotify) shell_ready_for_online, shell);

??????? g_object_add_weak_pointer (
??????????????? G_OBJECT (shell->priv->preparing_for_line_change),
??????????????? &shell->priv->preparing_for_line_change);


??????? // 通知后端进行长时逻辑操作
??????? g_signal_emit (
??????????????? shell, signals[PREPARE_FOR_ONLINE], 0,
??????????????? shell->priv->preparing_for_line_change);

??????? g_object_unref (shell->priv->preparing_for_line_change);
}

static void
shell_ready_for_online (EShell *shell,
??????????????????????? EActivity *activity,
??????????????????????? gboolean is_last_ref)
{

??????? // 引用从n到1 is_last_ref = true

??????? // 引用从1到n is_last_ref = false
??????? if (!is_last_ref)
??????????????? return;

?

??????? // 引用为1,说明后端操作结束,前端准备发出信号并进行收尾
??????? /* Increment the reference count so we can safely emit
???????? * a signal without triggering the toggle reference. */
??????? g_object_ref (activity);

??????? e_activity_set_state (activity, E_ACTIVITY_COMPLETED);

??????? g_object_remove_toggle_ref (
??????????????? G_OBJECT (activity), (GToggleNotify)
??????????????? shell_ready_for_online, shell);

??????? /* Finalize the activity. */
??????? g_object_unref (activity);

??????? shell->priv->online = TRUE;
??????? g_object_notify (G_OBJECT (shell), "online");
}

?

后端:
mail/e-mail-backend.c:

??????? // 后端关联信号进行长时操作
??????? g_signal_connect (
??????????????? shell, "prepare-for-online",
??????????????? G_CALLBACK (mail_backend_prepare_for_online_cb),
??????????????? shell_backend);

static void
mail_backend_prepare_for_online_cb (EShell *shell,
??????????????????????????????????? EActivity *activity,
??????????????????????????????????? EMailBackend *backend)
{
...

??????????????? // 对于标志activity引用+1

??????????????? // 当 e_mail_store_go_online长时操作结束后,自动调用mail_backend_store_operation_done_cb进行引用-1
??????????????? /* FIXME Not passing a GCancellable. */
??????????????? e_mail_store_go_online (
??????????????????????? CAMEL_STORE (service), G_PRIORITY_DEFAULT,
??????????????????????? NULL, (GAsyncReadyCallback)
??????????????????????? mail_backend_store_operation_done_cb,
??????????????????????? g_object_ref (activity));

...
}

/* Callback for various asynchronous CamelStore operations where
?* the EActivity's reference count is used as a counting semaphore. */
static void
mail_backend_store_operation_done_cb (CamelStore *store,
????????????????????????????????????? GAsyncResult *result,
????????????????????????????????????? EActivity *activity)
{
??????? /* FIXME Not checking result for error.? To fix this, we need
???????? *?????? separate callbacks to call different finish functions
???????? *?????? and then submit an EAlert on error. */

??????? g_object_unref (activity);
}

libemail-engine/e-mail-store-utils.c:
void
e_mail_store_go_online (CamelStore *store,
??????????????????????? gint io_priority,
??????????????????????? GCancellable *cancellable,
??????????????????????? GAsyncReadyCallback callback,
??????????????????????? gpointer user_data)
{
??????? GSimpleAsyncResult *simple;

??????? g_return_if_fail (CAMEL_IS_STORE (store));

??????? // 新建异步操作对象,设定操作结束后自动调用callback函数
??????? simple = g_simple_async_result_new (
??????????????? G_OBJECT (store), callback,
??????????????? user_data, e_mail_store_go_online);

?

??????? // 使用新线程进行长时操作mail_store_go_online_thread

??????? // 当mail_store_go_online_thread结束后自动调用GAsyncReadyCallback callback
??????? g_simple_async_result_run_in_thread (
??????????????? simple, (GSimpleAsyncThreadFunc)
??????????????? mail_store_go_online_thread,
??????????????? io_priority, cancellable);

??????? g_object_unref (simple);
}

static void
mail_store_go_online_thread (GSimpleAsyncResult *simple,
???????????????????????????? CamelStore *store,
???????????????????????????? GCancellable *cancellable)
{

??????? // 下面是长时操作
??????? CamelService *service;
??????? const gchar *display_name;
??????? GError *error = NULL;

??????? service = CAMEL_SERVICE (store);

??????? display_name = camel_service_get_display_name (service);
??????? if (display_name == NULL || *display_name == '\0')
??????????????? display_name = G_OBJECT_TYPE_NAME (service);

??????? camel_operation_push_message (
??????????????? cancellable, _("Reconnecting to '%s'"), display_name);

??????? if (CAMEL_IS_DISCO_STORE (store))
??????????????? camel_disco_store_set_status (
??????????????????????? CAMEL_DISCO_STORE (store),
??????????????????????? CAMEL_DISCO_STORE_ONLINE,
??????????????????????? cancellable, &error);

??????? else if (CAMEL_IS_OFFLINE_STORE (store))
??????????????? camel_offline_store_set_online_sync (
??????????????????????? CAMEL_OFFLINE_STORE (store),
??????????????????????? TRUE, cancellable, &error);

??????? if (error != NULL)
??????????????? g_simple_async_result_take_error (simple, error);

??????? camel_operation_pop_message (cancellable);
}

热点排行