繁体   English   中英

如果另一个线程进入循环,则退出循环

[英]Exit a loop if another thread enter in the

我有一个多线程问题。

我有一个方法可以对多个项目进行刷新。

在这种方法中,我遍历项目列表并刷新其属性之一。

该列表包含很多元素,我们必须做一些数学运算才能计算出它的属性。

该操作的当前代码如下所示:

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; ,进入调用,然后在检查之前设置为true的Invoke ,我不保证,有没有两个呼叫有到达调用之前我检查它在for循环。

那么当对方法进行新的调用时,如何在进入循环时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]);
        }
    });
}

这似乎工作得很好

我将通过以下方式进行操作:

private readonly object _refresherLock = new object();
private bool _isNewRefreshHere = false;
private AutoResetEvent _refresher = new AutoResetEvent(true);

public void AddItemsWithLayoutRefresh(IEnumerable<MyItem> items)
{
    lock (_refresherLock)
    {
         if (_isNewRefreshHere)
         {
             return;
         }

         _isNewRefreshHere = true;
    }

    _refresher.WaitOne();
    _isNewRefreshHere = false;

    _control.Invoke(() =>
    {
        AddItems(items);

        for (int i = 0; i < _guiItems.Count && !_isNewRefreshHere; i++)
        {
            _guiItems[i].Propriety = ComputePropriety(_guiItems[i]);
        }

        _refresher.Set();
    });
}

那是:

  • 您可以随时通过新操作取消当前更新。
  • 您一次最多只能排队一次更新。
  • 您可以保证没有跨线程冲突。
  • 您应该测试该代码,因为我没有进行测试。 :)

如果我是你,我将尝试创建一个线程安全的等待计数器。 您可以使用诸如Increment和Decrement之类的互锁方法。 这些基本上所做的是将它们作为原子操作递增该值,这被认为是线程安全的。 因此,您可以在调用调用之前增加变量。 这将使您知道等待队列中有多少个线程。 您可以在for循环完成之后以及Invoke块结束之前减小变量。 然后,您可以在for语句中检查等待线程的数量,如果数量大于1,则断开for。这样,您应该确切地知道执行链中有多少个线程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM