在单独的线程中添加进程列表<t>成员</t>

时间:2010-07-09 11:41:47

标签: c# visual-studio-2010

首先,这里有一些我想改进的伪代码。

        public List<ProcessData> Processes;
        System.Threading.Thread ProcessThread;
        void ProcessLoop()
        {
            while (true)
            {
                for (int i = 0; i < Processes.Count; i++)
                {
                    if (HasPriority(Processes[i]))
                    {
                        Process(Processes[i]);
                    }
                }
                System.Threading.Thread.Sleep(1000);
            }

        }
        void AddProcessData(ProcessData pd)
        {
            Processes.Add(pd);
            if (Suspended(ProcessThread))
                Resume(ProcessThread);
        }
        void Startup()
        {
            ProcessThread = new System.Threading.Thread(ProcessLoop);
            ProcessThread.Start();
        }

所以我想要做的是将'Sleep'替换为将挂起线程的代码,或让它等待直到某些内容添加到列表然后恢复它。我当然也需要它是线程安全的。

5 个答案:

答案 0 :(得分:1)

你想要的是一个事件。

编辑:使其成为线程安全的。

    public List<ProcessData> Processes;
    System.Threading.Thread ProcessThread;
    System.Threading.AutoResetEvent ProcessesChangedEvent = new System.Threading.AutoResetEvent(false);
    void ProcessLoop()
    {
        while (true)
        {
            // You might want to copy out the entire list as an array instead 
            // if HasPriority or Process take a long time.
            lock (Processes)
            {
                for (int i = 0; i < Processes.Count; i++)
                {
                    if (HasPriority(Processes[i]))
                    {
                        Process(Processes[i]);
                    }
                }
            }
            ProcessesChangedEvent.WaitOne(...); // timeout?
        }

    }
    void AddProcessData(ProcessData pd)
    {
        lock (Processes)
            Processes.Add(pd);
        ProcessesChangedEvent.Set(); // you can also use Monitor.PulseAll/Wait
    }
    void Startup()
    {
        ProcessThread = new System.Threading.Thread(ProcessLoop);
        ProcessThread.Start();
    }

答案 1 :(得分:1)

在您的情况下,最好的决定是使用下一个课程之一:ManualResetEventAutoResetEvent

答案 2 :(得分:1)

你真正需要的是BlockingQueue。您可以找到高质量的实施here。或者,如果您使用的是.NET Framework的v4,则可以使用内置的BlockingCollection类。请注意使用此类数据结构时代码的容易程度。

public class YourClass
{
  private BlockingQueue<ProcessData> m_Queue = new BlockingQueue<ProcessData();

  private void ProcessLoop()
  {
    while (true)
    {
      ProcessData item = m_Queue.Dequeue();
      if (HasPriority(item))
      {
        Process(item);
      }
    }
  }

  public void AddProcessData(ProcessData item)
  {
    m_Queue.Enqueue(item);
  }

  public void Startup()
  {
    var thread = new Thread(() => { ProcessLoop(); });
    thread.Start();
  }
}

答案 3 :(得分:0)

了解Microsoft的RX框架。 http://rxwiki.wikidot.com/start 在那里你可以每x秒获得一个事件然后做一些事情。 根本不需要启动线程。

或使用计时器,并检查已用完的事件。

答案 4 :(得分:0)

万一你确实只需要处理一次数据,这里有一些代码


        public Queue<ProcessData> Processes;
        System.Threading.Thread[] ProcessThreads = new System.Threading.Thread[5];
        System.Threading.Semaphore semToDo = new System.Threading.Semaphore(0,int.MaxValue);

        void ProcessLoop()
        {
            ProcessData pd; 

            while (true)
            {
                semToDo.WaitOne();
                lock (Processes)
                {
                    pd = Processes.Dequeue();                    
                }
                Process(pd);
            }
        }

        private void Process(ProcessData processData)
        {
            throw new NotImplementedException();
        }

        void AddProcessData(ProcessData pd)
        {
            lock (Processes)
            {
                Processes.Enqueue(pd);
            }
            semToDo.Release();
        }
        void Startup()
        {
            //you can even have multiple worker threads now!

            for(int i = 0; i < 5; i++)
                ProcessThreads[i] = new System.Threading.Thread(ProcessLoop);
            foreach (System.Threading.Thread t in ProcessThreads)
            {
                t.Start();
            }
        }