在 GIO 中,为啥这些异步文件 IO 操作永远不会完成? (适用于 C 和 Vala)

Posted

技术标签:

【中文标题】在 GIO 中,为啥这些异步文件 IO 操作永远不会完成? (适用于 C 和 Vala)【英文标题】:In GIO, why do these asynchronous file IO operations never complete? (applies to both C and Vala)在 GIO 中,为什么这些异步文件 IO 操作永远不会完成? (适用于 C 和 Vala) 【发布时间】:2012-06-03 04:58:27 【问题描述】:

我想执行异步文件 IO 操作。这是我在 Vala 中尝试做的简化版本:

void main(string[] args) 
    store_async();

    while(true)
        ;


async void store_async() 
    File file = File.new_for_path("settings.ini");

    stderr.printf("Checking if file exists...\n");
    if (!file.query_exists()) 
        stderr.printf("About to yield file.create_async...\n");
        try 
            yield file.create_async(FileCreateFlags.REPLACE_DESTINATION);
         catch (Error err) 
            error("Error creating file: %s\n", err.message);
        
        stderr.printf("Returned from file.create_async.\n");
    

    string data = "hello\n";
    string new_etag;
    stderr.printf("About to yield file.replace_contents_async...\n");
    try 
        yield file.replace_contents_async(
            data.data,
            null,
            false,
            FileCreateFlags.NONE,
            null,
            out new_etag);
     catch (Error err) 
        error("Error replacing contents: %s\n", err.message);
    

    stderr.printf("Returned from file.replace_contents_async.\n");

当我运行这个程序时,没有文件 settings.ini 存在,settings.ini 被创建并且我看到这个输出:

Checking if file exists...
About to yield file.create_async...
(hangs)

如果settings.ini 存在,则不会向其写入任何内容,我会看到以下输出:

Checking if file exists...
About to yield file.create_async...
(hangs)

如果我尝试在 C 中重现该问题,我也会遇到类似的问题。这是我的 C 代码(它不会复制上面的整个 vala 示例,只是创建文件的部分):

#include <glib.h>
#include <gio/gio.h>
#include <stdio.h>

void create_callback(GObject *source_object, GAsyncResult *res, gpointer user_data);
void write_contents();

GFile* file;

void main(int argc, char** argv) 
    g_type_init();

    fprintf(stderr, "Before file_new_for_path\n");
    file = g_file_new_for_path("settings.ini");

    fprintf(stderr, "Before file_query_exists\n");
    if (!g_file_query_exists(file, NULL)) 
        fprintf(stderr, "Before file_create_async\n");
        g_file_create_async(
                file,
                G_FILE_CREATE_REPLACE_DESTINATION,
                G_PRIORITY_DEFAULT,
                NULL,
                create_callback,
                NULL);
        fprintf(stderr, "After file_create_async\n");
     else 
        fprintf(stderr, "File already exists. Before write_contents\n");
        write_contents();
        fprintf(stderr, "File already exists. After write_contents\n");
    

    while(TRUE)
        ;


void create_callback(GObject *source_object, GAsyncResult *res, gpointer user_data) 
    fprintf(stderr, "In create_callback. Before write_contents.\n");
    write_contents();
    fprintf(stderr, "In create_callback. After write_contents.\n");


void write_contents() 
    fprintf(stderr, "In write_contents\n");

当我运行这个例子时,我看到了这个输出(假设settings.ini 不存在):

Before file_new_for_path
Before file_query_exists
Before file_create_async
After file_create_async
(hangs)

换句话说,create_callback 永远不会被调用。

我做错了什么?为什么我打电话给他们时,g_file_create_asyncg_file_replace_contents_async 不完整?

【问题讨论】:

【参考方案1】:

glib 中的异步实现要求您运行消息循环。如果没有,您的回调将如何以及何时被调用?

所以在 Vala 中只需添加:

var loop = new MainLoop();
loop.run();

在 C 中:

GMainLoop *loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
g_main_loop_unref(loop)

【讨论】:

以上是关于在 GIO 中,为啥这些异步文件 IO 操作永远不会完成? (适用于 C 和 Vala)的主要内容,如果未能解决你的问题,请参考以下文章

为啥说nodejs是异步非阻塞

为啥 HTTP 请求永远不会通过异步等待返回?

异步 GIO 服务器/客户端

Glib/Gio 异步或线程 UDP 服务器

同步IO, 异步IO的理解

lustre文件系统部署流程