多线程列表模式建议

时间:2015-05-21 11:31:44

标签: c# wpf multithreading design-patterns asynchronous

我制作了一个包含文件夹/文件扫描程序的应用程序。我遇到了线程结构的问题。

工作原理: 对于每个文件夹/文件,它找到它启动一个线程。每个线程中都有一个函数,它使用一个列表来检查是否找到了类似的项目,以便它可以添加到现有项目中。如果未找到,则会将该项添加到前面提到的列表中。线程是并行执行的(异步)。

问题: 因为它是异步的,所以它有时会在listcheck上失败。这是因为检查和添加到列表之间有一段时间。可能发生的事情是检查返回没有类似的项目,而肯定有。这将导致列表中出现相同的项目。

我还让线程彼此等待。我非常喜欢它在前端产生的效果。 (物品很好地实时添加到列表中)。但这需要很长时间才能获得很多文件夹/文件。

现在我正在考虑在函数之间进行混合,但我真的希望看到异步线程的速度和等待每个线程的安全性的组合。

有人有什么想法吗?

3 个答案:

答案 0 :(得分:3)

您应该锁定检查列表的整个代码部分并添加值。

这样的事情:

private void YourThreadMethod(object state)
{
    // long taking operation

    lock (dictionary)
    {
        if (!dictionary.ContainsKey(yourItemKey))
        {
            // construct object, long taking operation

            dictionary.Add(yourItemKey, createdObject);
        }
    }
}

通过这种方式,每个线程都必须等到list可以自由使用。如果你想要一个更高级的解决方案,你可以阅读ReaderWriterLockSlim类,它提供了更细粒度的解决方案。

答案 1 :(得分:2)

最恰当的方法是在ConcurrentDictionary<string, byte>类型为yourItemKeyotherwise adapt TKey and use a proper IEqualityComparerimplement IEquatable)时使用string

private readonly ConcurrentDictionary<string, byte> _list = new ConcurrentDictionary<string, byte>();
private void Foo(object state)
{
  // looong operation
  this._list.TryAdd(yourItemKey, 0);
}
public void Bar()
{
  // this is how to query the content
  this._list.Keys...;
}

背后的诀窍是不要使用过于复杂的对象作为键,可能需要处理或有外部引用(我更喜欢任何字符串表示),以及一个小类型的值,它只是作为一个标记

答案 2 :(得分:0)

我会考虑使用C#中的thread safe collections之一。对于您的情况,像ConcurrentBag这样的东西比使用锁更有效。

如果检查和添加之间存在时间延迟,您可以使用ConcurrentDictionary。它有一个TryAdd方法,如果具有相同键的项已经在字典中,它将返回false