异步执行时变量共享(C#与javascript)
2011-03-16 14:01
113 查看
C#中创建的委托实例,并且其中使用了方法中的局部变量,有可能会使此变量的生命周期变长(闭包),这一点与javascript是差不多的,但如果这个局部变量是变化中的(比如在循环中),会有一些微妙的不同。
C#的例子:
与C#同样,也存在变量共享的问题,alert出来的全是5。
下面我们来解决这个问题,如果共享变量不是我们所期望的,在C#中我们可以加入一个临时变量,将task的引用赋给临时变量t,而t的生命周期跟随各自的委托实例,解决了共享变量task的问题:
就可以达到我们所期望的效果,那我们以这种方式给javascript的代码改造一番:
但还是没有达到我们期望的效果。
根本原因是javascript的变量没有块级作用域,即使声明的变量j在for循环之内,它的作用域仍然是process函数的局部作用域,所以j的引用仍随循环发生着变化。知道原因了就好办了,一种做法是:
作用域,基础但不简单。
C#的例子:
文章。 再看看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 process(){ for(var i=0;i<5;i++){ (function(j){ setTimeout(function(){ alert(j); },0); })(i); } }其实,两者都是再包装一个函数(后一种是匿名),每次执行它时,它的作用域链包含了一个不同的调用对象(函数的实参其实是添加到这个调用对象的后面,而实参是指向是对当时共享变量的一个引用,共享变量的指向变化并不会引起实参的指向),所以这样才会达到我们期望的效果。
作用域,基础但不简单。
相关文章推荐
- Javascript异步执行时要小心的变量作用域
- javascript异步执行函数导致的变量变化问题解决思路
- 浅析javascript异步执行函数导致的变量变化问题解决思路
- javaScript 自执行函数—保留异步方法调用的内部变量
- 异步执行时变量共享(python)
- 使用async属性异步加载执行JavaScript
- c# 设置和取消文件夹共享及执行Dos命令
- C#执行异步操作的几种方式总结比较
- 多个页面共享JAVASCRIPT 变量,对象,函数
- C#异步执行任务的方法
- C#继承中构造函数,成员变量的执行顺序
- 「JavaScript」同步、异步、回调执行顺序之经典闭包setTimeout分析
- C# 异步执行SQL语句
- javascript异步执行的一些例子(未测试)
- JavaScript同步、异步、回调执行顺序之经典闭包setTimeout面试题分析
- C#中匿名方法变量共享原理分析
- 在C#的winForm程序中调用和执行javascript
- JavaScript同步、异步、回调执行顺序之setTimeout面试题分析
- C#执行异步操作的几种方式比较和总结
- c#中里有pl/sql匿名块和绑定变量在执行insert后获取当前序列值