我有一个执行一些数据处理的类:
class Processor
{
public Processor() {
// Load lot of data
}
public string GetResult(string input) {
// ...
}
}
我需要实现一个向此类公开 HTTP API 的服务。我使用 Owin 和 Microsoft.AspNet.* 库来托管 HTTP Web API。对于每个请求,它都会创建一个新线程来处理它,但我无法在每个请求上实例化
Processor
,因为在其构造函数中加载一些数据需要花费大量时间。另外,我无法重用不同线程中的一个实例,因为它不是设计为线程安全的。但我可以在服务启动时实例化 Processor
的多个实例,然后在它们之间分派工作。假设我的服务最多允许 20 个并发 HTTP 请求。我创建 20 个 Processor
实例并向类添加 Busy 标志:
class Processor
{
public bool Busy { get; set; }
// ...
}
我写了这样的
Dispatcher
类:
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
来调用了:
public class ServiceController : ApiController
{
static Dispatcher _dispatcher = new Dispatcher(20);
[Route("result")]
[HttpGet]
public string Result(string input)
{
return _dispatcher.GetResult(input);
}
}
它是否正确实现了我的目的? 我测试了它并且它有效,但我想知道我是否重新发明了轮子并且 .NET Framework 已经准备好用于我的案例,或者它是否可以更容易地实现。
基本上在将在线程中运行的类中,创建一个事件和事件处理程序。然后启动该任务的对象可以注册该事件。当任务引发它时(在这种情况下,您将在完成时引发事件),您可以做一些事情,即。给它更多的工作。
在将在子线程中运行的类中创建事件:
public event TaskCompleteEventHandler OnComplete;
public event TaskErrorEventHandler OnError;
在正在旋转类的对象中注册事件:
task.OnComplete += TaskComplete;
task.OnError += TaskComplete;
在调用类中创建将处理事件的函数:
public void TaskComplete()
{
//give the thread more work
}