【发布时间】:2014-10-30 17:59:31
【问题描述】:
我知道这些年来异步编程发生了很多变化。让我在 34 岁的时候就这么生疏让我有些尴尬,但我指望 StackOverflow 能让我跟上进度。
我想要做的是在一个单独的线程上管理一个“工作”队列,但是一次只处理一个项目。我想在这个线程上发布工作,它不需要将任何东西传回给调用者。当然,我可以简单地启动一个新的Thread 对象,并让它在共享的Queue 对象上循环,使用睡眠、中断、等待句柄等。但我知道从那以后事情变得更好了。我们有BlockingCollection、Task、async/await,更不用说可能抽象出很多内容的 NuGet 包了。
我知道“什么是最好的……”问题通常不受欢迎,所以我将改写为“目前推荐的……”使用内置 .NET 机制完成此类事情的方式最好。但是,如果第三方 NuGet 包可以简化很多事情,那也一样。
我考虑了一个TaskScheduler 实例,它的最大并发数固定为 1,但现在似乎有一种不那么笨重的方法来做到这一点。
背景
具体来说,在这种情况下,我要做的是在 Web 请求期间排队 IP 地理定位任务。同一个 IP 可能会多次排队等待地理定位,但该任务将知道如何检测到这一点,如果已经解决,则提前跳过。但请求处理程序只是将这些() => LocateAddress(context.Request.UserHostAddress) 调用放入队列,并让LocateAddress 方法处理重复工作检测。我使用的地理定位 API 不喜欢被请求轰炸,这就是为什么我想一次将其限制为单个并发任务。但是,如果允许该方法通过简单的参数更改轻松扩展到更多并发任务,那就太好了。
【问题讨论】:
-
我会使用
BlockingCollection。听起来像是一个简单的生产者/消费者。 -
@Zer0 这对于同步生产者/消费者模型很有用,但对于异步模型则不然。
-
@Servy No -
BlockingCollection非常适合异步的。那我写个例子吧。 -
同意它是一个简单的生产者/消费者。 .NET 中的并发集合可能会使“启动
new Thread(...)”场景更简单。我想我假设/希望 .NET(或流行的库)现在可能已经添加了一些可配置线程池的概念。 -
@Josh:我认为 Servy 的回答给了你需要的东西——即一种限制(异步)并发的方法。没有专用线程,也没有 FIFO 排序的保证,但听起来它可以满足您的需求。也就是说,如果你真的想要一个在线程上运行的队列,你可以使用
AsyncContext/AsyncContextThreadfrom my AsyncEx library。
标签: c# .net asynchronous concurrency task-parallel-library