ThreadPool 适合这种线程场景吗?

发布于 2024-09-04 11:13:13 字数 616 浏览 5 评论 0原文

我有一个场景,如果可能的话,我试图在用户实际需要结果之前预先获取结果的一些子元素,从而将其变成响应速度更快的 UI。我不清楚如何最好地处理线程,所以我希望有人可以提供一些建议。

场景

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

现有系统

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

目标

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

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

问题

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

I have a scenario that I'm trying to turn into a more responsive UI by pre-fetching some sub-elements of the results before they're actually required by the user if possible. I'm unclear on how best to approach the threading, so I'm hoping someone can provide some advice.

Scenario

There is search form (.NET rich client) that enable the user to select an account for a given customer. The user searches for given text to find a collection of customers which are then displayed in a result grid. Then when the user selects a customer, the list of accounts for that customer are searched for and displayed in a second grid for user selection in order to make up the final context (that is an account) to open.

Existing System

I have this all running in a request/response manner using regular background threading to resolve customers and accounts for a customer respectively in direct response to the user selections. The UI is locked/disabled (but responsive) until the accounts are found.

Goal

What I want to achieve is to commence fetching of the accounts for the top N customers before the user has selected them... Where N is the number of items being displayed in the grid.

As the user scrolls the grid, the newly displayed items will be added to the "queue" to be fetched.

Questions

  1. Is the thread pool an appropriate mechanism for managing the threads? If so, can you force just a single queued work item to jump up in priority? - e.g. if the user selects that customer before they have started/finished fetching.
  2. If not, what else should I be doing?
  3. Either way, are you aware of any good blog posts and/or open source projects that exhibit this functionality?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

唯憾梦倾城 2024-09-11 11:13:13

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

但是你不能(不应该)“碰撞”ThreadPool 线程,但我认为这无论如何都不会有用。

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

Yes, the threadpool is a good choice, maybe behind a Backgroundworker or .NET4's TaskParallel library.

But you cannot (should not) 'bump' a ThreadPool thread but I don't think that is going to be useful anyway.

What you should probably do is to use a thread-safe queue (of the top N items) and use 2+ threads to process the Queue. When an item is selected and not yet being processed you move it up or start a separate thread immediately.

后知后觉 2024-09-11 11:13:13

通过更新/解决方案...我遵循了 Henk 的< /a> 解决方案(某种程度上),这样我保留了工作项对象的队列,但仍然使用线程池处理它们。选定的项目通过将它们放在队列的前面(而不是后面)来“碰撞”[注意:为此需要一个特殊的集合]。

下面可能会详细描述它(代替代码)

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

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

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

总的来说,我确实让原本简单的工作变得更加困难,如果我能够使用 Framework 4,我肯定会考虑走 TPL 路线。

By way of an update / solution... I followed Henk's solution (sort of) such that I keep a queue of work item objects but I still process them using the ThreadPool. Selected items are 'bumped' by putting them on the front of the queue (rather than the back) [note: needed a special collection for this].

The following might describe it in detail (in lieu of code)

  • Modified Customer to keep a property of IList<Account> named KnownValues and also an object used for locking named KnownValuesSyncObject (since I want the KnownValues to be null when they aren't yet known).
  • Search form maintains an instance variable Deque<CustomerAccountLoadingWorkItem> (from PowerCollections)
  • A CustomerAccountLoadingWorkItem maintains a reference to the Customer it's meant to process for, as well as it's ManualResetEvent handle that it was created with.
  • In order to only start loading for visible items (i.e. not scrolled off the screen) I used answers from my other post to use Data Virtualization as a mechanism for queuing CustomerAccountLoadingWorkItem's as each 'page' was loaded. Immediately after adding to the work items queue, a task is added to the ThreadPool queue. The context/state for the ThreadPool.QueueUserWorkItem call was my _accountLoadingWorkItems queue.
  • The WaitCallback delegate launched by the ThreadPool, took the work item queue passed to it, then (using locks) dequeued the top item (if there wasn't one, then returned immediately); then processed that item. The function used was a static function as part of CustomerAccountLoadingWorkItem so that it could access it's private readonly state (that is, the Customer and ManualResetEvent)
  • At the end of processing the static processing function also sets the Customer.KnownValues (using the KnownValuesSyncObject for locking).
  • When the user selected a value in the Customers grid, in it's already separate thread (via BackgroundWorker) if the Customer.KnownValues isn't already filled (i.e. it's probably sitting in the queue somewhere), then it adds a new CustomerAccountLoadingWorkItem to the work item queue (but at the top!!! [this was why the Deque was required]) and also adds a new processing task to the ThreadPool. Then since it created the work item it calls ManaulResetEvent.WaitOne() to force waiting for the thread pool task to complete.

I hope that made sense...

Of note, since my solution still uses the ThreadPool when the user selects an item I still have to wait for currently running thread pool thread's to finish before my work item gets picked up, I figured that was OK and possibly even desirable seeing as though the resources used to query for the accounts (a webservice) will be semi-locked up it'll probably come up equivalently quick anyway (due to some poor architecting and a shared web service proxy).

Overall, I certainly made what should have been an easy-ish job somewhat more difficult and should I have been able to use Framework 4 I would have looked at going down the TPL route for sure.

空心↖ 2024-09-11 11:13:13

如果 .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-新线程池内部/

If .NET 4 is an option, might I recommend the new ConcurrentStack collection.

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

You can add all the items you want to pre-fetch and if an item is selected by the user, you can push that selection onto the stack making it the next instance to be retrieved. This works great with the new PLINQ and TPL and makes use of the new ThreadPool improvements in .NET 4.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文