这将是非常基本的,但是我们遇到了一个问题,无法缩小问题的范围。希望有人能对此有所了解。
我们有一个简单的静态类
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是卡夫卡制作人
答案 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
时它们才会被处理