悪徳商法?マニアックス ココログ支店

悪徳商法総合情報紹介ページ ~騙すなら、素敵にだまして~  本家「悪徳商法?マニアックス」は、こちら

« ストーカーmemo 10/22 | トップページ | Yahoo・Googleの言い分を、正しく読み込んでみる »

2007.10.22

C# Tips: バックグラウンドでRubyを実行する

C#から、Rubyを呼び出すことは出来るんだけど、普通に呼び出すとメインスレッドで実行されるので、UIがブロックされてしまう。そこで、Ruby専用のスレッドを作ってみた。

でも、DoWorkを待つ(Rubyと同期させる)のは、どうしよう?
何か良いアイデアがあったら、教えてください。

public class Ruby2 { public const string RubyDll = "msvcrt-ruby18";

[DllImport( RubyDll )]
public static extern void ruby_init();

[DllImport( RubyDll )]
public static extern System.Int32 rb_eval_string( [MarshalAs( UnmanagedType.LPStr )] string s );

private static EventWaitHandle NewItemEvent = new AutoResetEvent( false );
private static EventWaitHandle ExitThreadEvent = new ManualResetEvent( false );
private static WaitHandle[] EventArray = new WaitHandle[2] { NewItemEvent, ExitThreadEvent };
private static Queue _queue = new Queue();
private static Thread thread;

public delegate void func();

public static void Init()
{
thread = new Thread( ThreadRun );
thread.Start();
}

public static void Terminate()
{
ExitThreadEvent.Set();
thread.Join();
}

public static void ThreadRun()
{
ruby_init();

while ( WaitHandle.WaitAny( EventArray ) != 1 )
{
func dlg;
lock ( ((ICollection)_queue).SyncRoot )
{
dlg = _queue.Dequeue();
}
dlg();
}
}

public static void DoWork( func f )
{
lock ( ((ICollection)_queue).SyncRoot )
{
_queue.Enqueue( f );
NewItemEvent.Set();
}
}
}

使い方:

Ruby2.Init();
Ruby2.DoWork( delegate()
{
Ruby2.rb_eval_string( @"sleep(3);File.open('a.txt', 'w' ) { |f| f.puts Time.now.inspect }" );
Console.WriteLine( DateTime.Now.ToString() );
// formを呼び出す場合は、Invokeで
} );
Console.WriteLine( DateTime.Now.ToString() );
Ruby2.Terminate();

参考: producer スレッドと consumer スレッドを同期する

2007 10 22 [プログラム] | 固定リンク このエントリーを含むはてなブックマーク

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/26611/16838816

この記事へのトラックバック一覧です: C# Tips: バックグラウンドでRubyを実行する:

コメント

同期の一般的な作法なら Callback かポーリングですね。
Callback を使うなら非同期 delegate は考慮されましたか?
非同期 delegate のサンプルなら
http://codezine.jp/a/article/aid/139.aspx?p=1
あたりのが有用かと思いますが。

投稿者: G.O.R.N (2007/10/30 16:36:49)

非同期delegateは、今回の場合、使えないんです。
rb_init、rb_eval_string は、同じスレッドで呼ぶ必要があります。
ただ待つだけでcallback使うのもなんなので、mutexで待つことにしました。

投稿者: Beyond (2007/10/30 19:33:03)

コメントを書く