使用ThreadPools搜索对象列表

时间:2008-12-18 06:17:08

标签: c# wpf threadpool

我在列表中有这些容器对象(让我们称之为Container)。这些Container对象中的每一个依次在列表中具有DataItem(或派生词)。在典型情况下,用户将拥有15-20个Container对象,每个对象1000-5000 DataItems。然后有一些DataMatcher个对象可用于不同类型的搜索。这些工作大多都很好(因为我对它们进行了几百个单元测试),但是为了让我的WPF应用程序感觉活泼和响应,我决定我应该使用ThreadPool来执行此任务。因此,我有一个 DataItemCommandRunner ,它在Container对象上运行,并且基本上在列表中执行每个委托,它依次作为每个DataItem的参数;我使用ThreadPool为每个Container排队一个线程,这样理论上的搜索应该在多核计算机上尽可能高效。

这基本上是在 DataItemUpdater 类中完成的,如下所示:

public class DataItemUpdater
{
    private Container ch;
    private IEnumerable<DataItemCommand> cmds;

    public DataItemUpdater(Container container, IEnumerable<DataItemCommand> commandList)
    {
        ch = container;
        cmds = commandList;
    }

    public void RunCommandsOnContainer(object useless)
    {
        Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
        foreach (DataItem di in ch.ItemList)
        {
            foreach (var cmd in cmds)
            {
                cmd(sh);
            }
        }
        //Console.WriteLine("Done running for {0}", ch.DisplayName);
    }
}

RunCommandsOnContainer 的无用对象参数是因为我在使用和不使用线程时尝试使用它,其中一个需要一些参数。另外,将优先级设置为 AboveNormal 也只是一个实验。)

除了一个场景之外,这种方法都可以正常工作 - 当我使用AllWordsMatcher对象类型来查找包含所有搜索词的DataItem个对象时(与任何单词,精确短语或常规单词相对)例如表达。)

这是一个非常简单的基于somestring.Contains(eachWord)的对象,由单元测试支持。但这里有一些毛茸茸的陌生感。

RunCommandsOnContainer 使用ThreadPool个线程运行时,它将返回疯狂的结果。说我有这样的字符串:

var someString = "123123123 - just some numbers";

我跑了这个:

var res = someString.Contains("data");

当它运行时,这实际上将返回真的很多 - 我有调试信息,显示它返回true为空字符串和其他不包含数据的字符串。此外,即使字符串实际包含要查找的数据,它也会返回false。

这一切的踢球者?为什么我怀疑ThreadPool而不是我自己的代码?

当我为主线程中的每个Container运行 RunCommandsOnContainer()命令(即锁定UI和所有内容)时,它每次都能正常工作!它永远不会找到它不应该发生的任何东西,它永远不会跳过应该找到的任何东西。

然而,一旦我使用ThreadPool,它就会开始找到很多项它不应该,但有时候找不到应该的项目。

我意识到这是一个复杂的问题(尝试调试是痛苦的,这是肯定的!),但是对于为什么以及如何解决这个问题的任何见解都将非常感激!

谢谢!

符文

1 个答案:

答案 0 :(得分:2)

从您发布的片段中看起来有点难,但从症状判断我会看到AllWordsMatcher(寻找静态)。如果AllWordsMatcher是有状态的,您还应检查是否为每个线程创建了一个新实例。

更一般地说,我会查看匹配/搜索过程中涉及的所有实例,特别是在多线程时使用的工作对象。从过去的经验来看,问题通常就在那里。 (在这种情况下,很容易看到代表业务数据Container / DataItem的对象图)