1、创建Task
GTask *g_task_new (gpointer source_object,GCancellable *cancellable,GAsyncReadyCallback callback,gpointer callback_data);
source_object:GObject对象,拥有者
cancellable:可否取消
callback:task完成后调用函数
callback_data:task完成后调用函数数据参数
2、设置数据
void g_task_set_task_data(GTask *task, gpointer task_data , GDestroyNotify task_data_destroy);
处理函数使用task_data方式:typedef void (*GTaskThreadFunc)(GTask *task,gpointer source_object,gpointer task_data,GCancellable *cancellable);
3、同步执行和异步执行,注:
一定调用
g_task_return_pointer或者g_task_return_error返回
void g_task_run_in_thread(GTask *task,GTaskThreadFunc task_func);void g_task_run_in_thread_sync(GTask *task, GTaskThreadFunc task_func);
调用时机:调用task完成后的回调函数, GAsyncReadyCallback的调用时机是main event loop的下一次迭代。
4、执行回调函数
typedef void (*GAsyncReadyCallback) (GObject *source_object,GAsyncResult *res,gpointer data);
5、示例
extern "C"{
#include "glib.h"
#include "glib-object.h"
#include "gio/gio.h"
#include <stdio.h>
#include <stdlib.h>
}
typedef int CakeFlavor;
typedef int CakeFrostingType;
typedef struct {
guint radius;
CakeFlavor flavor;
CakeFrostingType frosting;
char *message;
} CakeData;
typedef GObject Cake;
static void cake_data_free(CakeData *cake_data)
{
printf("main thread %p: %s\n", g_thread_self(), __func__);
g_free(cake_data->message);
g_slice_free(CakeData, cake_data);
}
static Cake *bake_cake(GObject *self, guint radius, CakeFlavor flavor,
CakeFrostingType frosting, char *message,
GCancellable *cancellable, GError **error)
{
printf("end------sub thread %p: %s\n\n", g_thread_self(), __func__);
return (Cake *)g_object_new(G_TYPE_OBJECT, NULL);
}
static void bake_cake_thread(GTask *task, gpointer source_object,
gpointer task_data, GCancellable *cancellable)
{
GObject *self = (GObject *)source_object;
CakeData *cake_data = (CakeData *)task_data;
Cake *cake;
GError *error = NULL;
printf("\nstart-----sub thread %p: %s\n", g_thread_self(), __func__);
cake = bake_cake(self, cake_data->radius, cake_data->flavor,
cake_data->frosting, cake_data->message, cancellable,
&error);
if (cake)
g_task_return_pointer(task, cake, g_object_unref);
else
g_task_return_error(task, error);
if (g_task_set_return_on_cancel (task, FALSE)){
g_task_return_pointer (task, cake, g_object_unref);
}
}
static void baker_bake_cake_async(GObject *self, guint radius, CakeFlavor flavor,
CakeFrostingType frosting,
const char *message,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
CakeData *cake_data;
GTask *task;
printf("main thread %p: %s\n", g_thread_self(), __func__);
cake_data = g_slice_new(CakeData);
cake_data->radius = radius;
cake_data->flavor = flavor;
cake_data->frosting = frosting;
cake_data->message = g_strdup(message);
task = g_task_new(self, cancellable, callback, user_data);
g_task_set_task_data(task, cake_data, (GDestroyNotify)cake_data_free);
// g_task_set_return_on_cancel (task, TRUE);
g_task_run_in_thread(task, bake_cake_thread);
// g_task_set_check_cancellable(task,TRUE);
g_object_unref(task);
}
static Cake * baker_bake_cake_sync(GObject *self, guint radius, CakeFlavor flavor,
CakeFrostingType frosting,
const char *message,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
CakeData *cake_data;
GTask *task;
printf("main thread %p: %s\n", g_thread_self(), __func__);
cake_data = g_slice_new(CakeData);
cake_data->radius = radius;
cake_data->flavor = flavor;
cake_data->frosting = frosting;
cake_data->message = g_strdup(message);
task = g_task_new(self, cancellable, NULL, NULL);
g_task_set_task_data(task, cake_data, (GDestroyNotify)cake_data_free);
// g_task_set_return_on_cancel (task, TRUE);
g_task_run_in_thread_sync(task, bake_cake_thread);
Cake *cake;
GError *error = NULL;
cake = (Cake *)g_task_propagate_pointer (task, &error);
printf("baker_bake_cake_sync cake: %p\n", cake);
g_object_unref(task);
return cake;
}
static Cake *baker_bake_cake_finish(GObject *self, GAsyncResult *res,
GError **error)
{
g_return_val_if_fail(g_task_is_valid(res, self), NULL);
printf("main thread %p: %s\n", g_thread_self(), __func__);
return (Cake *)g_task_propagate_pointer(G_TASK(res), error);
}
static void my_callback(GObject *source_object, GAsyncResult *res,
gpointer user_data)
{
GObject *baker = (GObject *)source_object;
GMainLoop *loop = (GMainLoop *)user_data;
Cake *cake;
GError *error = NULL;
printf("main thread %p: %s\n", g_thread_self(), __func__);
cake = baker_bake_cake_finish(baker, res, &error);
printf("A cake is baked: %p\n", cake);
// But discard it. I prefer pudding.
g_object_unref(cake);
// Stop cooking.
g_main_loop_quit(loop);
}
int main(void)
{
GObject *baker = (GObject *)g_object_new(G_TYPE_OBJECT, NULL);
GCancellable *cancellable = g_cancellable_new();
GMainLoop *loop = g_main_loop_new(NULL, FALSE);
Cake * cake = baker_bake_cake_sync(baker, 10, 20, 30, "sync", cancellable, my_callback, loop);
g_object_unref(cake);
baker_bake_cake_async(baker, 10, 20, 30, "async", cancellable, my_callback, loop);
g_object_unref(cancellable);
printf("main thread %p: start event loop.\n", g_thread_self());
g_main_loop_run(loop);
g_main_loop_unref(loop);
g_object_unref(baker);
return EXIT_SUCCESS;
}
输出结果:
main thread 000001F6F9BED030: baker_bake_cake_syncstart-----sub thread 000001F6F9BEF0C0: bake_cake_threadend------sub thread 000001F6F9BEF0C0: bake_cakebaker_bake_cake_sync cake: 000001F6F9BEE140main thread 000001F6F9BED030: cake_data_freemain thread 000001F6F9BED030: baker_bake_cake_asyncmain thread 000001F6F9BED030: start event loop.start-----sub thread 000001F6F9BEF0C0: bake_cake_threadend------sub thread 000001F6F9BEF0C0: bake_cakemain thread 000001F6F9BED030: my_callbackmain thread 000001F6F9BED030: baker_bake_cake_finishA cake is baked: 000001F6F9BEE380main thread 000001F6F9BED030: cake_data_free