Vala言語で外部プロセスを実行する(スレッドを使用してGTK+のテキストビューに実行結果を表示・メモ)
ここでは「外部プロセスをバックグラウンド実行しつつ、出力をGTK+のテキストビューにリアルタイム表示する」でPythonを用いて行ったように、GTK+のテキスト入力欄に入力したコマンドを実行し、結果をテキストビュー上に表示するコードを作成した上でのメモを行う。
スレッドを使用する
子プロセスの出力を読み込んで処理しているときにGUIを固まらせない(メインループ上で処理しない)ようにするためにはPythonで行ったときと同様にスレッドを用いるのが便利で、Vala言語では
http://live.gnome.org/Vala/ThreadingSamples
のサンプルを参考にできる。
- 別スレッドの関数は戻り値の型を「void *」にする
- GLib.Thread.create()でその関数を指定し、必要に応じて戻り値の(GLib.Thread)オブジェクト(「weak GLib.Thread」と弱い参照にする)についてメンバ関数を呼び出して同期(メンバ関数join())などの制御を行う・同期可能にするには2番目の真偽値をtrueにする
- コンパイル時には--threadオプションを指定
スレッド機能が使用できない場合はGLib.Thread.supported()がfalseを返すので、メイン関数上でチェックするようにするとよい。
public static int main (string[] args) { if (! GLib.Thread.supported ()) { GLib.error ("This program needs threading support.\n"); return 1; } (スレッド使用時の処理...) return 0; }
スレッドを使用しない場合でもIOチャンネル(「Vala言語で外部プロセスを実行する(GLib.Process.spawn_async_with_pipes()を使用・メインループを用いない場合と出力メッセージの処理)」で扱っている)の監視機能を用いることである程度はGUIを固まらせないようにできるのだが、ここでは扱わない。
スレッドの詳しい扱い方はGLibのC言語のリファレンスなどが参考になる。
ここでは標準出力と標準エラー出力の処理にスレッドを用いるため、特にスレッドの同期を行ったりすることなどはしない。
別スレッド上でGUIに関する処理を行う場合の注意
PyGTKと同様、GTK+のGUIに関する処理を別スレッドの関数の中で行う場合は
- Gdk.threads_init()をGtk.main()より前に呼ぶ
- アプリケーションが(再現性なく)落ちるのを防ぐため、別スレッドの関数の中でGTK+のGUIに関する処理を行う開始位置にGdk.threads_enter()、終了位置にGdk.threads_leave()を記述
となる。
return文がありません?
手元で作成したコードをコンパイルしようとすると
[ファイル名].vala:[開始位置]-[終了位置]: error: missing return statement at end of method body public void *[関数名] () ^^^^^^^^^^^^^^^^^^^^^ Compilation failed: 1 error(s), 0 warning(s)
となってしまった。
上のサンプルのURLにあるサンプルコードでは別スレッドで実行される関数にreturn文はなく、そのサンプルコードをコピペしてコンパイルすることもできたのだが、自分で作成したコードでは(同じように書いているはずなのに)このようにエラーが出た。
色々試してみた結果、別スレッドで実行される関数の最後に「return null;」を書くことでエラーは回避でき、正常に動作もすることが分かった。
まとめると
スレッド関係の部分のみをまとめると下のような形になる。
void *threadfunc () { (処理...) Gdk.threads_enter (); (GTK+上の描画に関する処理...) Gdk.threads_leave (); (処理...) return null; } void func () { weak GLib.Thread t; try { t = GLib.Thread.create (threadfunc, true); // 2番目の引数はjoin()しなければfalseでOK (必要に応じてt.join()で同期) } catch (GLib.ThreadError e) { GLib.warning ("ThreadError: %s", e.message); } }
(「Vala言語で外部プロセスを実行する(スレッドを使用してGTK+のテキストビューに実行結果を表示・コード例)」に続く)
関連記事:
- 外部プロセスをバックグラウンド実行しつつ、出力をGTK+のテキストビューにリアルタイム表示する - PyGTKでの例
- Vala言語で外部プロセスを実行する(簡単な例・メモ)
- Vala言語で外部プロセスを実行する(簡単な例・コード例と出力結果)
- Vala言語で外部プロセスを実行する(GLib.Process.spawn_async_with_pipes()を使用・メインループを用いた例・メモ)
- Vala言語で外部プロセスを実行する(GLib.Process.spawn_async_with_pipes()を使用・メインループを用いた例・コード例)
- Vala言語で外部プロセスを実行する(GLib.Process.spawn_async_with_pipes()を使用・メインループを用いない場合と出力メッセージの処理)
- Vala言語で外部プロセスを実行する(スレッドを使用してGTK+のテキストビューに実行結果を表示・コード例)
- Vala言語で外部プロセスを実行する(スレッドを使用せずにGTK+のテキストビューに実行結果を表示するテスト)
参考URL:
- Valadoc: GLib.Process.spawn_async_with_pipes
- GLib リファレンスマニュアル(日本語訳・2.8系): プロセスの生成
- GLib リファレンスマニュアル(日本語訳・2.8系): メイン・イベント・ループ
- GLib リファレンスマニュアル(日本語訳・2.8系): IO チャンネル
使用したバージョン:
- Vala 0.7.4, 0.7.5