看来,如果给定的线程出于任何原因失败,这将导致无限循环。并行运行线程似乎导致无限循环
这是不是我写的代码,所以我甚至不能编辑它,但我觉得这里最明显的问题是,计数器变量totalActions
没有标记为挥发性,和结果线程没有看到最新的值。
因此,它看起来像是从未得到totalActions
的实际价值,它会一直等待吗?
这会导致线程递归运行吗?调试时,我发现正在执行的线程失败(抛出异常),它正在变得越来越叫了过来,并一遍又一遍....
public void PerformActions(List<Action> actions)
{
object actionLock = new object();
int totalActions = actionts.Count;
for(int x = 0; x < accounts.Count; x++)
{
int y = x;
new Thread(delegate()
{
actions[y].Invoke();
if(Interlocked.Decrement(ref totalActions) == 0)
{
lock(actionLock)
{
Monitor.Pulse(actionLock);
}
}
}).Start();
}
lock(actionLock)
{
if(totalActions > 0)
{
Monitor.Wait(actionLock);
}
}
}
更新
用法是这样的, myService
正在调用httpRequest
调用来从API服务中获取json请求。
Execute.InParallel(
new Action[]
{
() => { abc = myService.DoSomething(); },
() => { def = myService.DoSomethingElse(); }
});
此代码无关与TPL(比使用TPL就可以防止这种不正确的代码被写在首位的事实等。 ) – dlev 2013-05-01 19:53:40
那么根据MSDN文档,挥发性的使用应保持在最低限度,如果使用的话。主要用于内存非常有限的嵌入式系统。他们建议使用'lock'关键字或另一个锁定机制,如互斥锁和信号灯。另外,使用'Interlocked.Decrement()'可以首先防止这个问题。因为这是一个原子动作,意味着一次只能有一个线程工作。 – Nomad101 2013-05-01 19:53:41
@ Nomad101我知道在java中,你必须标记变量,以保证其他线程看到的值,否则将使用本地线程副本,这可能不是正确的值。在C#中,不正确的是 – loyalflow 2013-05-01 19:57:47