• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

异步执行时变量共享(C#与javascript)

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

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#中我们可以加入一个临时变量,将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);
    }
}
其实,两者都是再包装一个函数(后一种是匿名),每次执行它时,它的作用域链包含了一个不同的调用对象(函数的实参其实是添加到这个调用对象的后面,而实参是指向是对当时共享变量的一个引用,共享变量的指向变化并不会引起实参的指向),所以这样才会达到我们期望的效果。

作用域,基础但不简单。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#面向对象编程实例-猜拳游戏发布时间:2022-07-10
下一篇:
c#(.net)对dbf(arcgisshp属性表)的操作(验证版)发布时间:2022-07-12
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap