多线程循环在IIS上不起作用

时间:2018-08-10 10:36:07

标签: c# asp.net multithreading

这将是非常基本的,但是我们遇到了一个问题,无法缩小问题的范围。希望有人能对此有所了解。

我们有一个简单的静态类

public static class SomeLogger
{
    private static ConcurrentQueue<LogObject> queue = new ConcurrentQueue<LogObject>();
    private static bool isRunning = false;        
    public static void Start()
    {
        if (isRunning) return;
        Task.Run(() => Process());
    }
    public static void Stop()
    {
        isRunning = false;
    }

    public static void AddToQueue(LogObject obj)
    {
        queue.Enqueue(obj);
    }

    public static void Process()
    {
        isRunning = true;

        using (var p = new SomeClass())
        {
            while (isRunning)
            {
                //see if something is in the queue object if yes process it 
                if(queue.TryDequeue(out LogObject d))
                {
                    //Do some stuff
                }
                Thread.Sleep(1000);
            }
        }
    }
}

我们在开始时在应用程序事件监听器中调用此类  -调用SomeLogger.Start  -将isRunning设置为true

到目前为止一切都很好

我们运行Web应用程序并多次调用SomeLogger.Add()进行日志记录

但是当我们在本地运行该程序时,即在iisexpress上,while循环将拾取所有添加队列事件并对其进行处理。

在我们服务器上的IIS上执行相同操作时,只会选择队列中的第一条“添加”和“最后添加”消息。

我们不确定为什么吗?你们在上面的代码中发现任何错误。.

环境: 简单的Asp.Net Web API SomeClass是卡夫卡制作人

1 个答案:

答案 0 :(得分:-2)

这是使用TPL数据流库的解决方案

public static class SomeLogger
{
    private static readonly BufferBlock<LogObject> _buffer = new BufferBlock<LogObject>();
    private static Task _consumer;
    private static CancellationTokenSource _cts;

    public static void Start()
    {
        if (_cts != null && !_cts.IsCancellationRequested) return;

        _cts = new CancellationTokenSource();
        _consumer = ConsumeAsync(_buffer, _cts.Token);
    }

    public static void Stop()
    {
        _cts.Cancel();
    }

    public static void AddToQueue(LogObject log)
    {
        SendToBuffer(_buffer, log);
    }

    private static void SendToBuffer(ITargetBlock<LogObject> target, LogObject log)
    {
        target.Post(log);
    }

    private static async Task ConsumeAsync(IReceivableSourceBlock<LogObject> source, CancellationToken cancellationToken)
    {
        while (await source.OutputAvailableAsync(cancellationToken))
        {
            var log = await source.ReceiveAsync();

            // do some stuff
        }
    }

您甚至可以使用AddToQueue将其添加到缓冲区中,直到调用Start时它们才会被处理