代码改变世界

多线程协同

2014-12-04 10:00  江上渔者  阅读(242)  评论(0编辑  收藏  举报
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.IO;

namespace WaitOneTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();

            Console.ReadLine();
        }

        private HashSet<string> m_sAllWork; // 所有工作
        private Queue<string> m_qWaiting; // 等待队列
        private AutoResetEvent m_WorkingEvent = null; // 工作事件
        private AutoResetEvent m_ResumeEvent = null; // 继续事件
        private Thread m_MonitorThread = null; // 监控线程
        private Thread m_WorkingThread = null; // 工作线程
        private Thread m_PatrolThread = null; // 巡逻线程

        public Program()
        {
            MyTrace.m_bEnabled = true;
            MyTrace.WriteLine("Program method starting.");

            m_sAllWork = new HashSet<string>();
            m_qWaiting = new Queue<string>();
            m_WorkingEvent = new AutoResetEvent(false);
            m_ResumeEvent = new AutoResetEvent(false);
            m_MonitorThread = new Thread(new ThreadStart(DoMonitor));
            m_WorkingThread = new Thread(new ThreadStart(DoWork));
            m_PatrolThread = new Thread(new ThreadStart(DoPatrol));
            m_MonitorThread.Start();
            m_WorkingThread.Start();
            m_PatrolThread.Start();

            Thread.Sleep(10000);

            m_PatrolThread.Abort();
            m_WorkingThread.Abort();
            m_MonitorThread.Abort();

            MyTrace.WriteLine("Program method ending.");
        }

        private void DoMonitor()
        {
            MyTrace.WriteLine("DoMonitor method starting.");
            try
            {
                lock (m_qWaiting)
                {
                    for (int i = 0; i < 5; i++)
                    {
                        if (!m_sAllWork.Contains(i.ToString()))
                        {
                            m_sAllWork.Add(i.ToString());
                            m_qWaiting.Enqueue(i.ToString());
                        }
                    }
                    if (m_qWaiting.Count > 0)
                        m_ResumeEvent.Set();  // 恢复工作线程(因为工作线程可能处于空闲等待)
                }
                do
                {
                    // 随机时间内产生一个工作任务
                    Thread.Sleep(new Random().Next(100, 2000));
                    int i = new Random().Next(1, 10000);
                    lock (m_qWaiting)
                    {
                        if (!m_sAllWork.Contains(i.ToString()))
                        {
                            m_sAllWork.Add(i.ToString());
                            m_qWaiting.Enqueue(i.ToString());
                            m_ResumeEvent.Set(); // 恢复工作线程(因为工作线程可能处于空闲等待)
                        }
                    }
                } while (true);
            }
            catch (Exception e)
            {
                MyTrace.WriteLine("DoMonitor method - caught Exception - " + e.Message);
            }
            MyTrace.WriteLine("DoMonitor method ending.");
        }

        private void DoWork()
        {
            MyTrace.WriteLine("DoWork method starting.");
            try
            {
                do
                {
                    MyTrace.WriteLine("DoWork method signal.");
                    m_WorkingEvent.Set(); // 工作心跳
                    string filename = null;
                    try
                    {
                        lock (m_qWaiting)
                        {
                            filename = m_qWaiting.Dequeue();
                        }
                    }
                    catch (InvalidOperationException)
                    {
                        MyTrace.WriteLine("Queue is empty now.");
                        m_ResumeEvent.WaitOne(500); // 空闲时间(该值要小于巡逻周期值)
                        continue;
                    }
                    MyTrace.WriteLine("DoWork method process - " + filename);
                    try
                    {
                        Thread.Sleep(new Random().Next(100, 2000));
                    }
                    catch (Exception e)
                    {
                        MyTrace.WriteLine("DoWork method process - caught Exception - " + e.Message);
                        lock (m_qWaiting)
                        {
                            m_qWaiting.Enqueue(filename); // 失败的文件加回队列末尾
                        }
                    }
                } while (true);
            }
            catch (Exception e)
            {
                MyTrace.WriteLine("DoWork method - caught Exception - " + e.Message);
            }
            MyTrace.WriteLine("DoWork method ending.");
        }

        private void DoPatrol()
        {
            MyTrace.WriteLine("DoPatrol method starting.");
            try
            {
                do
                {
                    MyTrace.WriteLine("Wait for work method to signal.");
                    // Wait for work method to signal.
                    if (m_WorkingEvent.WaitOne(1000)) // 巡逻周期
                    {
                        MyTrace.WriteLine("Work method signaled.");
                    }
                    else
                    {
                        MyTrace.WriteLine("Timed out waiting for work method to signal.");
                        m_WorkingThread.Interrupt();
                    }
                } while (true);
            }
            catch (Exception e)
            {
                MyTrace.WriteLine("Thread - caught Exception - " + e.Message);
            }
            MyTrace.WriteLine("DoPatrol method ending.");
        }
    }

    public class MyTrace
    {
        public static bool m_bEnabled = false;
        public static void WriteLine(string strMsg)
        {
            if (m_bEnabled)
            {
                lock (typeof(MyTrace))
                {
                    Console.WriteLine(string.Format("{0} {1}", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff"), strMsg));
                }
            }
        }
    }
}

输出:

2014-12-04 12:40:26.905 Program method starting.
2014-12-04 12:40:26.952 DoWork method starting.
2014-12-04 12:40:26.953 DoWork method signal.
2014-12-04 12:40:26.953 DoMonitor method starting.
2014-12-04 12:40:26.975 DoPatrol method starting.
2014-12-04 12:40:26.975 Wait for work method to signal.
2014-12-04 12:40:26.975 Work method signaled.
2014-12-04 12:40:26.975 Wait for work method to signal.
2014-12-04 12:40:27.079 Queue is empty now.
2014-12-04 12:40:27.079 DoWork method signal.
2014-12-04 12:40:27.079 DoWork method process - 0
2014-12-04 12:40:27.079 Work method signaled.
2014-12-04 12:40:27.079 Wait for work method to signal.
2014-12-04 12:40:28.079 Timed out waiting for work method to signal.
2014-12-04 12:40:28.079 Wait for work method to signal.
2014-12-04 12:40:28.087 DoWork method process - caught Exception - 线程已从等待
状态中断。
2014-12-04 12:40:28.087 DoWork method signal.
2014-12-04 12:40:28.088 DoWork method process - 1
2014-12-04 12:40:28.088 Work method signaled.
2014-12-04 12:40:28.088 Wait for work method to signal.
2014-12-04 12:40:28.866 DoWork method signal.
2014-12-04 12:40:28.866 DoWork method process - 2
2014-12-04 12:40:28.866 Work method signaled.
2014-12-04 12:40:28.866 Wait for work method to signal.
2014-12-04 12:40:29.866 Timed out waiting for work method to signal.
2014-12-04 12:40:29.866 Wait for work method to signal.
2014-12-04 12:40:29.872 DoWork method process - caught Exception - 线程已从等待
状态中断。
2014-12-04 12:40:29.873 DoWork method signal.
2014-12-04 12:40:29.874 DoWork method process - 3
2014-12-04 12:40:29.875 Work method signaled.
2014-12-04 12:40:29.875 Wait for work method to signal.
2014-12-04 12:40:30.409 DoWork method signal.
2014-12-04 12:40:30.409 DoWork method process - 4
2014-12-04 12:40:30.409 Work method signaled.
2014-12-04 12:40:30.409 Wait for work method to signal.
2014-12-04 12:40:30.727 DoWork method signal.
2014-12-04 12:40:30.727 DoWork method process - 0
2014-12-04 12:40:30.728 Work method signaled.
2014-12-04 12:40:30.728 Wait for work method to signal.
2014-12-04 12:40:31.720 DoWork method signal.
2014-12-04 12:40:31.720 DoWork method process - 4408
2014-12-04 12:40:31.721 Work method signaled.
2014-12-04 12:40:31.722 Wait for work method to signal.
2014-12-04 12:40:31.847 DoWork method signal.
2014-12-04 12:40:31.847 DoWork method process - 7897
2014-12-04 12:40:31.847 Work method signaled.
2014-12-04 12:40:31.847 Wait for work method to signal.
2014-12-04 12:40:32.549 DoWork method signal.
2014-12-04 12:40:32.549 DoWork method process - 2
2014-12-04 12:40:32.550 Work method signaled.
2014-12-04 12:40:32.550 Wait for work method to signal.
2014-12-04 12:40:33.550 Timed out waiting for work method to signal.
2014-12-04 12:40:33.551 Wait for work method to signal.
2014-12-04 12:40:33.557 DoWork method process - caught Exception - 线程已从等待
状态中断。
2014-12-04 12:40:33.558 DoWork method signal.
2014-12-04 12:40:33.558 DoWork method process - 9683
2014-12-04 12:40:33.559 Work method signaled.
2014-12-04 12:40:33.559 Wait for work method to signal.
2014-12-04 12:40:34.560 Timed out waiting for work method to signal.
2014-12-04 12:40:34.560 Wait for work method to signal.
2014-12-04 12:40:34.567 DoWork method process - caught Exception - 线程已从等待
状态中断。
2014-12-04 12:40:34.568 DoWork method signal.
2014-12-04 12:40:34.568 DoWork method process - 3389
2014-12-04 12:40:34.569 Work method signaled.
2014-12-04 12:40:34.569 Wait for work method to signal.
2014-12-04 12:40:35.569 Timed out waiting for work method to signal.
2014-12-04 12:40:35.569 Wait for work method to signal.
2014-12-04 12:40:35.579 DoWork method process - caught Exception - 线程已从等待
状态中断。
2014-12-04 12:40:35.580 DoWork method signal.
2014-12-04 12:40:35.580 DoWork method process - 2
2014-12-04 12:40:35.581 Work method signaled.
2014-12-04 12:40:35.582 Wait for work method to signal.
2014-12-04 12:40:36.208 DoWork method signal.
2014-12-04 12:40:36.208 DoWork method process - 6355
2014-12-04 12:40:36.209 Work method signaled.
2014-12-04 12:40:36.209 Wait for work method to signal.
2014-12-04 12:40:36.823 DoWork method signal.
2014-12-04 12:40:36.823 DoWork method process - 9683
2014-12-04 12:40:36.824 Work method signaled.
2014-12-04 12:40:36.824 Wait for work method to signal.
2014-12-04 12:40:36.939 Thread - caught Exception - 正在中止线程。
2014-12-04 12:40:36.954 DoWork method process - caught Exception - 正在中止线程
。
2014-12-04 12:40:36.964 DoMonitor method - caught Exception - 正在中止线程。
2014-12-04 12:40:36.967 Program method ending.
2014-12-04 12:40:36.999 DoWork method - caught Exception - 正在中止线程。