我有一個類至極執行一些數據處理:如何在多個處理器之間分派工作?
class Processor
{
public Processor() {
// Load lot of data
}
public string GetResult(string input) {
// ...
}
}
我需要實現一個服務至極公開HTTP API這一類。我使用Owin和Microsoft.AspNet。* libs來託管HTTP Web API。對於每個請求,它創建一個新的線程來處理它,但是我無法在每個請求上實例化Processor
,因爲在構造器中加載一些數據需要很長時間。此外,我不能重用來自不同線程的一個實例,因爲它不是線程安全的。但是我可以在服務啓動時實例化Processor
的幾個實例,然後在它們之間調度工作。假設我允許多達20個併發HTTP請求用於我的服務。我創建的Processor
20個實例,並添加忙標誌到類:
class Processor
{
public bool Busy { get; set; }
// ...
}
我寫Dispatcher
類是這樣的:
public class ServiceController : ApiController
{
static Dispatcher _dispatcher = new Dispatcher(20);
[Route("result")]
[HttpGet]
public string Result(string input)
{
return _dispatcher.GetResult(input);
}
}
:
class Dispatcher
{
readonly Processor[] _processors;
readonly SemaphoreSlim _semaphore;
public Dispatcher(int maxProcessors)
{
_semaphore = new SemaphoreSlim(maxProcessors);
_processors = new Processor[maxProcessors];
// Instantiate Processors, etc...
}
public string GetResult(string input)
{
try
{
_semaphore.Wait(); // Surplus requests will wait here.
Processor processor;
lock (_processors)
{
// It is guaranteed that such processor exists if we entered the semaphore.
processor = _processors.First(p => !p.Busy);
processor.Busy = true;
}
var result = processor.GetResult(input);
processor.Busy = false;
return result;
}
finally
{
_semaphore.Release();
}
}
}
然後我基本上可以ApiController調用它通過Dispatcher
它是否爲我的目的正確實施? 我測試了它,它可以工作,但我不知道我是否重新創建了輪子,並且.NET Framework已經有所準備用於我的案例,或者它可以更容易地實現。
https://msdn.microsoft.com/en-us/library/dd267312 – SLaks
@SLaks這是不太清楚如何在我的情況下使用'BlockingCollection',因爲我不僅需要分配工作項目,還需要收集結果。假設我有一些從'BlockingCollection'消耗的工人,我應該等到相應的結果準備好並獲得它。這是可以解決的,但我不知道它比這更容易... – greatvovan
看起來像一個非常好的實施給我。我不知道可以處理你的用例的.Net配置。如果處理器數量總是等於最大併發請求數量,那麼信號量可能是多餘的(較低級別的信號量已經可以保護處理器池免於飢餓);但是,如果Processor類受CPU限制而非IO限制,則可能需要將處理器池大小調整爲可用處理內核的數量,這樣可最大限度地減少併發線程之間的上下文切換,並可能獲得更好的整體性能。 – BlueStrat