我有一个多线程问题。
我有一个方法被调用来刷新几个项目。
在这个方法中,我迭代一个项目列表并刷新它的一个属性。
这个列表有很多元素,我们必须做一些数学来计算它的属性。
此操作的当前代码如下所示:
public void AddItemsWithLayoutRefresh(IEnumerable<MyItem> items){
_control.Invoke(()=>{
AddItems(items);
for(int i =0;i<_guiItems.Count;i++){
//The goal is to have a condition here to "break" the loop and let the next call to RefreshLayout proceed
_guiItems[i].Propriety = ComputePropriety(_guiItems[i]);
}
});
}
问题是我可能有 4 个电话,目前只是在Invoke
. 我必须完成“AddItems”方法,但关于“for”循环中的所有内容,如果我知道它将在之后执行,我可以毫无问题地中止它。
但是如何以线程安全的方式做到这一点呢?
如果我private bool _isNewRefreshHere;
在进入 Invoke 之前将 a , 设置为 true ,然后签入Invoke
,我不保证在我在 for 循环中检查之前没有两个调用已经到达 Invoke 。
那么break
当对我的方法进行新调用时,我该如何进入循环呢?
解决方案 基于 Andrej Mohar 的回答,我执行了以下操作:
private long m_refreshQueryCount;
public void AddItemsWithLayoutRefresh(IEnumerable<MyItem> items){
Interlocked.Increment(ref m_refreshQueryCount);
_control.Invoke(()=>{
Interlocked.Decrement(ref m_refreshQueryCount);
AddItems(items);
for(int i =0;i<_guiItems.Count;i++){
if (Interlocked.Read(ref m_refreshQueryCount) > 0)
{
break;
}
_guiItems[i].Propriety = ComputePropriety(_guiItems[i]);
}
});
}
这似乎工作得很好