【问题标题】:Cycle through ConcurrentQueue<T> indefinitely using either Timer/Stopwatch based event使用基于 Timer/Stopwatch 的事件无限期循环遍历 ConcurrentQueue<T>
【发布时间】:2017-07-13 06:34:41
【问题描述】:

在我的CheckQueue() 方法中,我想做的是不断地从队列中读取(通过调用AppQ.Connect(Time))和TryDequeue 从队列中取出每个项目。经过一段时间(可能是一分钟左右)后,我想回到队列 - 再次连接,检查它是否有一些元素(AppQ.Count),读取它们(TryDequeue())并无限期地执行此过程。

这是针对将成为 Windows 服务(目前是用于测试目的的 Windows 窗体应用程序)的应用程序,该服务将每天运行一整天,并在某些机器上运行的任何应用程序出现停机时提醒我们开发人员。我知道我将不得不使用While-Loop,但我不确定是同时使用基于Timer 的事件还是Stopwatch

更多上下文:我也有一种感觉,我应该考虑使用do-while 循环而不是while,因为前者执行一些操作(通过调用AppQ.Connect(time) 加载消息)然后检查退出条件(如果AppQ.Count &lt;= 0),而while 则相反。

考虑到它是线程安全的,我应该使用BlockingCollection&lt;T&gt; 吗?

有什么建议吗?

 public class APPInfo
 {
        public String Machine { get; set; }
        public String IP { get; set; }
        public String Port { get; set; }
        public String App { get; set; }
        public ClientApplicationState Status { get; set; }
        public String Message { get; set; }
        public String TimeStamp { get; set; }
        public String CPUUse { get; set; }
        public String MemoryUse { get; set; }
        public String TotalCPUUse { get; set; }
        public String TotalMemoryUse { get; set; }
 }

public static ConcurrentQueue<APPInfo> AppQ = new ConcurrentQueue<APPInfo>();

 public static void Connect(Int16 Time)
 {    
       AppQ.Enqueue(new APPInfo { Machine = "One", IP = "127.0.0.1", Port = "23000", App = "TestServer1", Status = ClientApplicationState.OK, TimeStamp = DateTime.Now.ToString(), CPUUse = "80.0", MemoryUse = "81.0", TotalCPUUse = "86.0", TotalMemoryUse = "87.0" });

       AppQ.Enqueue(new APPInfo { Machine = "One", IP = "127.0.0.1", Port = "23001", App = "TestServer2", Status = ClientApplicationState.ERROR, TimeStamp = DateTime.Now.ToString(), CPUUse = "82.0", MemoryUse = "83.0", TotalCPUUse = "88.0", TotalMemoryUse = "89.0" });

       AppQ.Enqueue(new APPInfo { Machine = "Two", IP = "127.0.0.2", Port = "23002", App = "TestServer3", Status = ClientApplicationState.WARNING, TimeStamp = DateTime.Now.ToString(), CPUUse = "84.0", MemoryUse = "85.0", TotalCPUUse = "90.0", TotalMemoryUse = "91.0" });        
 }

 private void CheckQueue()
 {
     AppIP.Connect(50);
     APPInfo first = new APPInfo();         

     if (AppIP.AppQ.Count > 0)
     {
         AppIP.AppQ.TryDequeue(out first);

        MessageBox.Show(first.App, first.IP, first.Port, first.Status.ToString(), first.Message, first.TimeStamp, first.CPUUse, first.MemoryUse, first.Machine, first.TotalCPUUse, first.TotalMemoryUse + "\n");
     }
     else
     {
          MessageBox.Show("There is nothing in the queue to process.", "Important Note", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
     }
 }

杂项:人们可以在我可能出错的地方发布 cmets,而不是仅仅投反对票而不给出理由

【问题讨论】:

  • 你最好使用 Rx 之类的东西,或者至少,正如你已经提到的,一个阻塞集合。
  • @NumLock 我一直在不懈地搜索,但找不到任何与 Rx 相关的示例。你能为我指出正确的方向吗?我以前从未使用过它。
  • 他可能最好在 ConcurrentQueue 周围创建一个包装器,添加 Enqueue /Dequeue 方法。然后要么在有东西排队进行处理时触发一个事件,要么直接调用一个循环直到队列为空的例程。

标签: c# while-loop do-while concurrent-queue


【解决方案1】:

为了不时检查队列,您需要设置一个计时器:

 CheckTimer = new System.Threading.Timer(CheckQueue, null, TimeSpan.FromMilliseconds(1000), TimeSpan.FromMilliseconds(1000));

您应该在初始化服务时创建计时器。

在您的 CheckQueue 方法中,您将需要一个循环来处理队列中的所有数据。

private void CheckQueue(object dummy)
{
    // The dummy is null, its there because it is a Timer event.
    AppIP.Connect(50);

    AppInfo appInfo;
    while(AppQ.TryDequeue(out appInfo))
    {
        // Process the appInfo
    }
}

请注意,来自 System.Threading 的计时器将在不同的线程中运行,即使当前事件仍在运行,下一个事件的处理也会发生!

【讨论】:

  • 你在哪里使用CheckTimer
  • 另外,参数化对象有什么作用?你的回答很模糊嘿嘿。看看能不能更新一下? @Casperah
  • 我已经添加了一些cmets来回答你的问题,但是答案有什么问题,为什么是-1?
  • 在 TryDequeue 之前,您在哪里检查队列中是否有实际项目? @Casperah
  • 根据文档,如果队列中有任何内容,TryDequeue 将返回 true,如果队列为空,则返回 false msdn.microsoft.com/en-us/library/dd287208(v=vs.110).aspx
猜你喜欢
  • 2013-03-19
  • 2014-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多