2012-04-28 5 views
2

現在、いくつかのvalaを学習しようとしています。チュートリアルを読んだ後、Javaで書かれたいくつかのアプリケーションをvalaに移植したかったのです。Vala:スレッドを作成するとプロパティが失われます。

したがって、私はフォルダの変更を監視するアプリケーションを作成しようとしました。このモニタは別のスレッドとして起動する必要があります。そのため、アプリケーションは監視する他の処理を実行できます。 Javaの簡単な仕事。

ランナー:

public class App : Object 
    { 
    private const string FOLDER_TO_WATCH = "/home/chr/Work/vala-monitor-test/tmp/"; 

    public App() { 

     GLib.MainLoop loop = new GLib.MainLoop(); 

     stdout.printf("Folder: %s\n", FOLDER_TO_WATCH); 

     try { 
      var daemon = new MonitorDaemon(File.new_for_path(FOLDER_TO_WATCH)); 
      unowned Thread<void*> t = Thread.create<void*>(daemon.watch, true); 
     } 
     catch (ThreadError err) { 
      stderr.printf("Error occured: %s", err.message); 
     } 
     catch (MonitorError err) { 
      stderr.printf("Error occured: %s", err.message); 
     } 

     stdout.printf("waiting..\n"); 

     loop.run(); 

    } 

    static int main(string[] args) 
    {   

     if (!Thread.supported()) { 
      stderr.printf ("Cannot run without thread support.\n"); 
      return 1; 
     } 

     new App(); 
     return 0; 

    } 

} 

モニタークラス:

errordomain MonitorError { 
    NOT_A_DIRECTORY 
} 

public class MonitorDaemon : Object { 

    // properties 
    public File watched_folder { get; construct set; } 

    // internal 
    private bool _stop = false; 


    public MonitorDaemon (File folder_to_watch) throws MonitorError { 

     if (folder_to_watch.query_file_type (FileQueryInfoFlags.NONE) != FileType.DIRECTORY) { 
      stderr.printf("Unable to watch: Not a directory\n"); 
      throw new MonitorError.NOT_A_DIRECTORY("Not a directory"); 
     } 

     this.watched_folder = folder_to_watch; 

     stdout.printf("Ready to watch %s\n", this.watched_folder.get_path()); 

    } 

    public void* watch() { 

     try { 
      FileMonitor monitor = this.watched_folder.monitor_directory (FileMonitorFlags.NONE); 
      monitor.changed.connect(event_happened); 
     } 
     catch (IOError err) { 
      stderr.printf("Error occured: %s", err.message); 
     } 

     stdout.printf("Started watching folder: %s\n", this.watched_folder.get_path()); 

     while (!this._stop) { } 

     stdout.printf("Stopped watching folder: %s\n", this.watched_folder.get_path()); 

     return null; 

    } 

    public void stop() { 
     // cleanup..    
     this._stop = true; 
    }   

    private void event_happened (File file, File? other_file, FileMonitorEvent event_type) { 
     stdout.printf("File '%s': %s\n", file.get_path(), event_type.to_string()); 
    } 

} 

監視するための方法をいくつかの研究を行った後、私は次のコードになってしまった(ところでStackOverflowの上のヒットを得ました)メソッドMonitorDaemon.watchのスレッドを作成するときに、コンストラクタで設定されたプロパティが再びnullになり、コマンドラインで次の出力が発生します。

Folder: /home/chr/Work/vala-monitor-test/tmp/ 
Ready to watch /home/chr/Work/vala-monitor-test/tmp/ 
waiting.. 

(process:7159): GLib-GIO-CRITICAL **: g_file_monitor_directory: assertion `G_IS_FILE (file)' failed 

(process:7159): GLib-GObject-WARNING **: invalid (NULL) pointer instance 

(process:7159): GLib-GObject-CRITICAL **: g_signal_connect_object: assertion `G_TYPE_CHECK_INSTANCE (instance)' failed 

(process:7159): GLib-GIO-CRITICAL **: g_file_get_path: assertion `G_IS_FILE (file)' failed 
Started watching folder: (null) 
+0

解決方法:同じtry..catch節でスレッドとして実行されるfnを含むクラスを初期化しないでください。上記のエラーが発生します。しかし、なぜ??? – cr0

+1

Valaは参照カウントです。 try {}ブロックを終了すると、unrefされてから解放されます。 – lethalman

+1

@lethalman:コメントを回答にコピーして受け入れることができます。 – jacknad

答えて

3

Valaは参照カウントされている。 try {}ブロックを終了すると、unrefされてから解放されます。 MonitorDaemonをどこかに生かしておく必要があります。

関連する問題