C# 多线程循环在IIS上不工作

C# 多线程循环在IIS上不工作,c#,asp.net,multithreading,C#,Asp.net,Multithreading,这将是非常基本的,但我们遇到了一个问题,无法缩小问题的范围。希望有人能对此有所启发 我们有一个简单的静态类 public static class SomeLogger { private static ConcurrentQueue<LogObject> queue = new ConcurrentQueue<LogObject>(); private static bool isRunning = false; public s

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

我们有一个简单的静态类

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。添加多次日志记录

但是,当我们在本地(即在iisexpress上)运行此程序时,while循环将拾取所有addthequeue事件并对其进行处理

当在我们的服务器上的IIS上执行相同的操作时,只拾取队列中的第一条添加和最后一条添加消息

我们不知道为什么?你们在上面的代码中看到的任何错误

环境: 简单的Asp.NETWebAPI
SomeClass是卡夫卡制作人

这里有一个使用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时才会处理它们。

什么是//做一些事情?确定没有引发异常?我在代码中没有看到任何重置isRunning的地方。可能不是解决方案,但您可能希望替换if queue.TryDequeue。。。使用while queue.TryDequeue…我没有发现任何错误,我同意Patrick的观点,问题可能出在处理逻辑上。建议使用Task.Delay1000.Wait,而不是Thread.Sleep1000,以确保一致性,我会将进程方法设置为私有。这与你的问题无关,尽管如此,我深表歉意。由于这种情况发生在服务器上而不是本地,所以可能是连接问题。您能否验证AddToQueue是否在每次调用中都被命中?感觉代码是好的,所以我猜是有一个错误,就像Patrick说的或其他什么。其他想法:你可能还想用任务替换Thread.Sleep语句。延迟,作为Thread.Sleep阻塞线程,然后不能用于其他任何事情。这解决了什么问题?