2

非同期ファイル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_asyncしないのですか?g_file_replace_contents_async

4

1 に答える 1

5

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)
于 2012-05-28T23:03:06.390 に答える