如何在多个处理器之间分配工作?

时间:2017-04-21 15:20:57

标签: c# .net multithreading asp.net-web-api

我有一个类,它执行一些数据处理:

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请求。我创建了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已经准备好用于我的情况,或者它是否可以更容易实现。

1 个答案:

答案 0 :(得分:0)

基本上在将要在线程中运行的类中,创建一个事件和事件处理程序。然后旋转此任务的对象可以注册到该事件。当它被任务引发时(在这种情况下你会在事件完成时引发事件)你可以做一些事情,即。给它更多的工作。

在将在子线程中运行的类中创建事件: public event TaskCompleteEventHandler OnComplete; public event TaskErrorEventHandler OnError;

在正在旋转类的对象中注册您的事件:

task.OnComplete += TaskComplete;
task.OnError += TaskComplete;

在将处理事件的调用类中创建函数:

public void TaskComplete()
{
//give the thread more work
}