非同期実行時の変数共有(C〓とjavascript)

2168 ワード

C(※)で作成された委託例では、方法における局所変数を使用して、この変数のライフサイクルを長くすることがあります.この点はjavascriptと同じですが、この局部変数が変化中(例えばサイクル中)であると、微妙に違ってきます.
C〓〓の例:
void Process()

{

    foreach (ITask task in GetTasks())

    {

        ThreadPool.QueueUserWorkItem(new WaitCallback(

            delegate{

                task.DoWork();

            })

        );

    }

}

非同期的にタスクのセットを実行する必要がありますが、最後にはその一部だけが実行される可能性があります.その理由は、匿名の方法による変数共有であり、趙さんの文章を参照することができます.
javascriptを見て、setTimeoutを使って非同期を作る場合:
function process(){

    for(var i=0;i<5;i++){

        setTimeout(function(){

            alert(i);

        },0);

    }

}

C(※)と同様に変数共有の問題もありますが、alertが出てくるのは全部5です.
以下でこの問題を解決します.もし共有変数が私達の期待したものではないなら、C((abs)に臨時変数を入れて、taskの参照を臨時変数tに賦課します.tのライフサイクルは各自の委託例に従って、共有変数taskの問題を解決しました.
void Process()

{

    foreach (ITask task in GetTasks())

    {

        ITask t=task;

        ThreadPool.QueueUserWorkItem(new WaitCallback(

            delegate{

                t.DoWork();

            })

        );

    }

}

私たちが期待している効果を達成することができます.この方法でjavascriptのコードを改造します.
function process(){

    for(var i=0;i<5;i++){

        var j=i;

        setTimeout(function(){

            alert(j);

        },0);

    }

}

しかし、私たちが期待していた効果はまだ達成されていません.
根本的な理由は、javascriptの変数はブロックレベルの作用領域がないため、たとえ宣言された変数jがforループ内にあるとしても、その作用領域は依然としてprocess関数の局所的な作用領域であるため、jの参照はサイクルとともに変化している.原因がわかれば簡単です.
function wrap(fn,data){

    setTimeout(function(){

        fn(data);

    },0);

}  

function process(){

    for(var i=0;i<5;i++){

        wrap(alert,i);

    }

}

もう一つのやり方は:
function process(){

    for(var i=0;i<5;i++){

        (function(j){

            setTimeout(function(){

                alert(j);

            },0);

        })(i);

    }

}
実は、両方はもう一つの関数を包装しています.(後の方は匿名です.)そのたびに実行します.
スコープチェーンには異なる呼び出しオブジェクトが含まれています.
変数の1つの参照を共有していますが、変数の指向性の変化は、実際の参照を引き起こすことはありません.
スコープ、基本は簡単ではない.