我正在编写一个ASP.NET队列处理器。用户将登录并上传数据文件到站点,然后单击开始处理数据文件。
我在系统上有一个Windows服务,它等待项目到达队列并处理它们。到目前为止一切正常,除了队列中的项目似乎迷路了。我相信静态成员正在失去范围,但我不确定如何解决它。
我考虑过在文件中写入文件,但是状态更新通常会成为性能杀手。
将数据输入和退出服务的最佳方法是什么?
Windows服务如下:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;
using System.Timers;
namespace MyMonitorService
{
public class MyMonitor : ServiceBase
{
#region Members
private System.Timers.Timer timer = new System.Timers.Timer();
private static Queue<String> qProjectQueue = new Queue<String>();
private static Mutex mutexProjectQueue = new Mutex(false);
private Boolean bNotDoneYet = false;
#endregion
#region Properties
public static String Status { get; private set; }
#endregion
#region Construction
public MyMonitor ()
{
this.timer.Interval = 10000; // set for 10 seconds
this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed);
Status = String.Empty;
}
#endregion
private void timer_Elapsed (object sender, ElapsedEventArgs e)
{
try
{
if (!this.bNotDoneYet)
{
this.bNotDoneYet = true;
for (;;)
{
MyMonitor.mutexProjectQueue.WaitOne();
if (MyMonitor.qProjectQueue.Count == 0)
{
EventLog.WriteEntry("MyMonitor", "The queue is empty", EventLogEntryType.Information);
break;
}
String strProject = MyMonitor.qProjectQueue.Dequeue();
EventLog.WriteEntry("MyMonitor", String.Format("The project {0} was dequeued", strProject), EventLogEntryType.Information);
MyMonitor.mutexProjectQueue.ReleaseMutex();
// Do something that updates MyMonitor.Status up to thousands of times per minute
}
}
this.bNotDoneYet = false;
}
catch (Exception ex)
{
EventLog.WriteEntry("MyMonitor", ex.Message, EventLogEntryType.Error);
}
}
public static void EnqueueProjects (params String[] astrProjects)
{
try
{
String strMessage = String.Format("The following projects were added to the queue:\n{0}", String.Join("\n", astrProjects));
EventLog.WriteEntry("MyMonitor", strMessage, EventLogEntryType.Information);
if (astrProjects == null)
return;
MyMonitor.mutexProjectQueue.WaitOne();
foreach (String strProject in astrProjects)
MyMonitor.qProjectQueue.Enqueue(strProject);
MyMonitor.mutexProjectQueue.ReleaseMutex();
}
catch (Exception e)
{
EventLog.WriteEntry("MyMonitor", e.Message, EventLogEntryType.Error);
}
}
#region Service Start/Stop
[STAThread]
public static void Main ()
{
ServiceBase.Run(new MyMonitor());
}
protected override void OnStart (string[] args)
{
try
{
EventLog.WriteEntry("MyMonitor", "MyMonitor Service Started", EventLogEntryType.Information);
this.timer.Enabled = true;
}
catch (Exception e)
{
EventLog.WriteEntry("MyMonitor", e.Message, EventLogEntryType.Error);
}
}
protected override void OnStop ()
{
try
{
EventLog.WriteEntry("MyMonitor", "MyMonitor Service Stopped", EventLogEntryType.Information);
this.timer.Enabled = false;
}
catch (Exception e)
{
EventLog.WriteEntry("MyMonitor", e.Message, EventLogEntryType.Error);
}
}
#endregion
}
}
答案 0 :(得分:1)
回答一般性问题如何解决这个问题(仍然不确定手头的代码):
取决于您的要求。从“简单”到“高端”:
关于您的代码:
首先想到的是我的想法:如果队列碰巧是空的,一旦你打破了计时器事件而且bNotDoneYet
永远不会重置为假 - &gt;新的参赛作品不会被考虑?
此外,您的生产者/消费者模式似乎对我不利。我习惯了轻量级(简化):
制片:
lock (_syncRoot) {
_queue.Enqueue(obj);
if (_queue.Count == 1) Monitor.Pulse(_syncRoot);
}
消费者:
lock (_syncRoot) {
while (_queue.Count < 1) {
try {
Monitor.Wait(_syncRoot);
} catch (ThreadInterruptedException) {}
}
var obj = _queue.Dequeue();
}