2010/07/14


JScript.NETはMicrosoftが.NET Framework向けに拡張したJavasSriptで、Common Language Runtime(CLR)上で動作するJavaScript実装です。
CLR上ではC#、VB.NET等が動作しますが、JScript.NETは言語がJavaScriptという事もあって実はC#やVB.NET等と同等に使えない機能がいくらかあります。
JavaScriptは動的言語です。オブジェクトにプロパティを生やしてメソッドにしたり、prototypeを弄ったり、eval()で関数を生成したりも出来ます。つまりコンパイルするとは言えど、型が動的に変えられる言語です。
その為、.NET Frameworkの機能の一つであるDelegateが使えません。.NET FrameworkのThreadはDelegateという関数型拘束によりスレッドを安全に呼び出せる様になっています。この関数型拘束に緩い拘束なJavaScript(JScript)の関数を渡す事は出来ないのです。
MSDNでもJScriptのDelegate利用制限が書かれています。
ThreadStart デリゲート

[JScript] JScript では、.NET Framework のデリゲートを利用することができます。ただし、独自に定義することはできません。

http://msdn.microsoft.com/ja-jp/library/system.threading.threadstart(VS.71).aspx
Delegate.CreateDelegate()というメソッドも存在しますが、こちらもJScriptからは利用出来ません。
じゃぁDelegateを引数に取るThreadはJScriptから作れないじゃないか!そう思っておられる方が殆どだと思います。

いえ、出来ます。

import System
import System.Reflection
import System.CodeDom.Compiler
import System.Threading
import Microsoft.CSharp

/**
 * createThread()
 * @param   f   thread function
 * @param   a   argument passing to function
 * @return  thread object
 */
var createThread = (function() {
    var source = [
        "using System.Threading;",
        "public class ThreadInvoker {",
        "  private Microsoft.JScript.Closure func;",
        "  private object arg = null;",
        "  public ThreadInvoker(Microsoft.JScript.Closure func, object arg) { this.func = func; this.arg = arg; }",
        "  private void invokerThread() { func.Invoke(null, new object[]{this.arg}); }",
        "  public Thread createInvoker() { return new Thread(invokerThread); }",
        "}",
    ].join("\n");

    var cp = CodeDomProvider.CreateProvider("CSharp");
    var cps = new CompilerParameters();
    cps.ReferencedAssemblies.Add("Microsoft.JScript.dll");
    cps.GenerateInMemory = true;
    var cr = cp.CompileAssemblyFromSource(cps, source);
    var asm = cr.CompiledAssembly;
    return function(f, a) {
        var tt : Type = asm.GetType("ThreadInvoker");
        var args = new System.Object[2];
        args[0] = f;
        args[1] = a;
        return tt.InvokeMember(
            "createInvoker",
            BindingFlags.InvokeMethod,
            null,
            Activator.CreateInstance(tt, args),
            null);
    };
})();
C#上で書かれたスレッドインボーカをメモリ内でコンパイルして、それにJScriptの関数、正しくはクロージャを渡します。
ここから先はCLRなので、どうとでも出来るはずでC#からMicrosoft.JScript.Closureのメソッドを叩く事も出来ます。
これを使えば
var th = createThread(function(v) {
    for (var n = 1; n <= 6; n++) {
        Thread.Sleep(200);
        print("thread" + n + " " + v);
    }
}, "foo");

th.Start();

Thread.Sleep(200);
print("main1");
th.Suspend();
Thread.Sleep(200);
print("main2");
Thread.Sleep(200);
print("main3");
th.Resume();
こんなコードで thread1 foo
main1
main2
main3
thread2 foo
thread3 foo
thread4 foo
thread5 foo
thread6 foo
こんな動作をさせる事も出来ます。JavaScript(JScript)でスレッドが使えると色々とやりたくなってきます。JScriptでサーバアプリなんて事も簡単に出来そうですね。
ちなみに、このcreateThread()を使うと、ウェブサーバなんかも書けたりします。試しに書いてみたらコードの少なさ(createThreadは除いて)に少し驚きました。JScript.NET & C# ばんざい!
import System
import System.Reflection
import System.CodeDom.Compiler
import System.Threading
import Microsoft.CSharp

/**
 * createThread()
 * @param   f   thread function
 * @param   a   argument passing to function
 * @return  thread object
 */
var createThread = (function() {
    var source = [
        "using System.Threading;",
        "public class ThreadInvoker {",
        "  private Microsoft.JScript.Closure func;",
        "  private object arg = null;",
        "  public ThreadInvoker(Microsoft.JScript.Closure func, object arg) { this.func = func; this.arg = arg; }",
        "  private void invokerThread() { func.Invoke(null, new object[]{this.arg}); }",
        "  public Thread createInvoker() { return new Thread(invokerThread); }",
        "}",
    ].join("\n");

    var cp = CodeDomProvider.CreateProvider("CSharp");
    var cps = new CompilerParameters();
    cps.ReferencedAssemblies.Add("Microsoft.JScript.dll");
    cps.GenerateInMemory = true;
    var cr = cp.CompileAssemblyFromSource(cps, source);
    var asm = cr.CompiledAssembly;
    return function(f, a) {
        var tt : Type = asm.GetType("ThreadInvoker");
        var args = new System.Object[2];
        args[0] = f;
        args[1] = a;
        return tt.InvokeMember(
            "createInvoker",
            BindingFlags.InvokeMethod,
            null,
            Activator.CreateInstance(tt, args),
            null);
    };
})();

import System.Net
import System.Net.Sockets

var listener = new System.Net.Sockets.TcpListener(IPAddress.Parse("127.0.0.1"), 8080);
listener.Start();

while (true) {
    createThread(function(client) {
        var stream = client.GetStream();
        var buf = new System.Byte[client.ReceiveBufferSize];
        var bytesRead = stream.Read(buf, 0, buf.length);
        var str = [
            "HTTP/1.0 200 OK",
            "Content-Type: text/html",
            "",
            "<html><body>",
            "<b>hello world</b>: " + (new Date).toString(),
            "</body></html>",
        ].join("\r\n");
        var bytes = System.Text.Encoding.Default.GetBytes(str);
        stream.Write(bytes, 0, bytes.length);
        stream.Close();
        client.Close();
    }, listener.AcceptTcpClient()).Start();
}
マルチスレッドウェブサーバです。カッコイー!
Posted at by



2010/07/10


echo/ > touch.txt
Posted at by



2010/07/03


ゴッ...ゴホンゴホン...
Go Programming [Paperback]
Go Programming [Paperback]
John P. Baugh (Author)
No customer reviews yet. Be the first.
Price: $19.99 & eligible for FREE Super Saver Shipping on orders over $25. Details
In Stock.
Ships from and sold by Amazon.com. Gift-wrap available.
Want it delivered Tuesday, July 6? Order it in the next 0 hours and 37 minutes, and choose One-Day Shipping at checkout. Details
3 new from $19.24


サイトはここ。
Go Programming

Welcome to the official website accompanying the book, Go Programming . The book can be purchased fr...

http://www.goprogrammingbook.com/
twitterアカウントはここ。さっきfollowされて気づいた。
Posted at by