我有一段代码,应该由少于 N 的最大线程数执行,并且线程调用 someFunction() 的顺序应该反射(reflect)在它们进入该部分的顺序中,即先进先出顺序。
如果我使用 Semaphore我无法控制线程进入该部分的顺序。
"There is no guaranteed order, such as FIFO or LIFO, in which blocked threads enter the semaphore."
初步尝试:
class someClass
{
static volatile Semaphore semaphore;
...
someClass()
{
semaphore = new Semaphore(N,N)
}
someType someFunction(InputType input)
{
try
{
semaphore.WaitOne();
/* Section Begins */
var response = someHeavyJob(input); // submitted to the server
return response;
/* Section Ends */
}
finally
{
semaphore.Release();
}
}
}
如果我将信号量和并发队列组合起来,如下所示,线程可能会返回对其他线程带来的请求的响应,这将需要对代码的其他部分进行重大更改。 针对以下问题的 .NET 4.5 解决方案是什么:
- 代码段中允许的最大线程数低于 N
- 线程进入该部分的顺序是 FIFO
线程将获得其所带来的请求的响应(而不是其他线程所带来的请求的响应)
class someClass { static volatile ConcurrentQueue<someType> cqueue; static volatile Semaphore semaphore; ... someClass() { cqueue = new ConcurrentQueue<someType>(); semaphore = new Semaphore(N,N) } someType someFunction(Request request) { try { cqueue.enqueue(request); semaphore.WaitOne(); Request newrequest; cqueue.TryDequeue(out newrequest); /* Section Begins */ var response = someHeavyJob(Request newrequest); // submitted to the server return response; /* Section Ends */ } finally { semaphore.Release(); } } }
更新: 我澄清一下我的问题: SomeHeavyJobs() 函数是对正在处理此作业的服务器的阻塞调用。
更新2: 谢谢大家的解答。郑重声明:我最终使用了 FIFO Semaphore
最佳答案
“如果我将信号量和并发队列组合起来,如下所示,线程可能会返回对其他线程带来的请求的响应,这将需要对代码的其他部分进行重大更改。”
我不想这么说,但我会建议“更改代码的其他部分”,尽管我不知道这会有多大的“意义”。
通常,按照您的建议,可以通过对包含对原始类实例的引用的消息进行排队来满足这样的要求,以便可以将响应“返回”到请求它们的对象。如果发起者都是某个“消息处理程序”类的后代,那么调用该函数的线程(应该是消息处理程序的成员)会更容易。一旦线程执行了该功能,它们就可以调用消息处理程序的“onCompletion”方法。 “onCompletion”可以发出发起者正在等待的事件信号(同步),也可以将某些内容排队到发起者的私有(private) P-C 队列中(异步)。
因此,一个 BlockingCollection、一个消费者线程以及明智地使用 C++/C# 继承/多态性应该可以完成这项工作。
奇怪的是,这几乎正是我当前的嵌入式 ARM 项目被迫要做的事情。用于配置/调试/日志的命令行界面线程现在非常大,即使在“Thumb,优化大小”模式下也需要大量 600 个字的堆栈。它不再被允许直接调用 SD 文件系统,现在必须将自己排队到运行 SD 卡的线程(它具有系统中运行 FAT32 的最大堆栈),并等待 SD 线程的信号量调用其方法并在完成后向信号量发出信号。
这是确保调用按顺序进行并且始终有效的经典方法。它基本上是一个只有一个线程的线程池。
就像其他发帖者所写的那样,任何其他方法都可能是,呃……“勇敢”。
关于c# - 最多有 N 个线程按 FIFO 顺序执行的代码部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11049221/