ThreadPool适合这种线程场景吗?

时间:2010-06-03 16:06:45

标签: c# .net multithreading search threadpool

我有一个场景,我试图通过在用户实际需要之前预先获取结果的一些子元素来变成响应更快的UI。我不清楚如何最好地接近线程,所以我希望有人可以提供一些建议。

方案

有一种搜索表单(.NET富客户端),使用户可以为给定的客户选择一个帐户。用户搜索给定文本以查找随后显示在结果网格中的客户集合。然后,当用户选择客户时,将搜索该客户的帐户列表并在第二个网格中显示以供用户选择,以便构成要打开的最终上下文(即帐户)。

现有系统

我将这一切都以请求/响应方式运行,使用常规后台线程分别解决客户和客户帐户,直接响应用户选择。在找到帐户之前,UI被锁定/禁用(但是响应)。

目标

我想要实现的是在用户选择之前开始为前N个客户提取帐户...其中N是网格中显示的项目数。

当用户滚动网格时,新显示的项目将被添加到要获取的“队列”中。

问题

  1. 线程池是否是管理线程的适当机制?如果是这样,您是否可以强制只有一个排队的工作项优先跳? - 例如如果用户在开始/完成提取之前选择该客户。
  2. 如果没有,我还应该做些什么?
  3. 无论哪种方式,您是否了解任何展示此功能的博客文章和/或开源项目?

3 个答案:

答案 0 :(得分:2)

是的,线程池是一个不错的选择,可能在Backgroundworker或.NET4的TaskParallel库之后。

但你不能(不应该)'碰撞'一个ThreadPool线程,但我认为无论如何都不会有用。

您应该做的是使用线程安全队列(前N项)和使用2+线程来处理队列。选择某个项目但尚未处理时,您可以将其移动或立即启动单独的线程。

答案 1 :(得分:1)

通过更新/解决方案...我遵循Henk's解决方案(排序),以便保留工作项对象的队列,但我仍然使用ThreadPool处理它们。选中的项目通过将它们放在队列的前面(而不是后面)来“碰撞”[注意:需要一个特殊的集合]。

以下内容可能会详细描述(代替代码)

  • 修改Customer以保留名为 KnownValues IList<Account>属性,以及用于锁定名为 KnownValuesSyncObject 的对象(因为我想知道KnownValues当它们还不知道时为空。)
  • 搜索表单维护实例变量Deque<CustomerAccountLoadingWorkItem>(来自PowerCollections
  • CustomerAccountLoadingWorkItem维护对其要处理的客户的引用,以及它创建时的ManualResetEvent句柄。
  • 为了仅开始加载可见项目(即不在屏幕上滚动),我使用my other post的答案使用Data Virtualization作为在加载每个“页面”时排队CustomerAccountLoadingWorkItem的机制。添加到工作项队列后,立即将任务添加到ThreadPool队列。 ThreadPool.QueueUserWorkItem调用的上下文/状态是我的_accountLoadingWorkItems队列。
  • 由ThreadPool启动的WaitCallback委托,将传递给它的工作项队列,然后(使用锁)使顶部项目出列(如果没有,则立即返回);然后处理该项目。使用的函数是一个静态函数,作为CustomerAccountLoadingWorkItem的一部分,以便它可以访问它的私有只读状态(即Customer和ManualResetEvent)
  • 在处理结束时,静态处理函数还设置Customer.KnownValues(使用KnownValuesSyncObject进行锁定)。
  • 当用户在Customers网格中选择一个值时,如果Customer.KnownValues尚未填充(即它可能位于某个队列中),则它已经是单独的线程(通过BackgroundWorker),然后添加一个新的CustomerAccountLoadingWorkItem到工作项队列(但在顶部!!! [这就是需要Deque的原因])并且还向ThreadPool添加了一个新的处理任务。然后,因为它创建了工作项,所以它调用ManaulResetEvent.WaitOne()来强制等待线程池任务完成。

我希望这是有道理的......

值得注意的是,由于我的解决方案仍然使用ThreadPool,当用户选择一个项目时,我仍然需要等待当前运行的线程池线程在我的工作项被拾取之前完成,我认为这是可以的,甚至可能需要看到好像用于查询帐户(网络服务)的资源将被半锁定,无论如何它都可能相当快(由于一些糟糕的架构和共享的Web服务代理)。

总的来说,我当然认为本来应该是一项简单易用的工作有点困难,如果我能够使用框架4,我肯定会考虑沿着TPL路线前进。

答案 2 :(得分:0)

如果选择.NET 4,我可以推荐新的ConcurrentStack集合。

http://msdn.microsoft.com/en-us/library/dd267331(v=VS.100).aspx

您可以添加要预取的所有项目,如果用户选择了某个项目,您可以将该选择推送到堆栈,使其成为下一个要检索的实例。这适用于新的PLINQ和TPL,并利用.NET 4中新的ThreadPool改进。

http://channel9.msdn.com/shows/Going+Deep/Erika-Parsons-and-Eric-Eilebrecht--CLR-4-Inside-the-new-Threadpool/