C#While Loop in Worker Thread用于监听命令和响应

时间:2011-12-01 06:35:40

标签: c# multithreading

问题概述:

我尝试使用线程(while..loop)来监听用户的命令。如果用户发送命令,它将在类(LoopingWorkerThread)中的全局变量中分配新值。

我不明白我是否将线程睡眠值设置为低于10毫秒,并且我不会得到任何响应(它在ListenCommand方法中)。看起来全局参数被覆盖" _CommandReceived"在该方法中,可能处理器运行得很快并且忽略参数的值已经改变(" _CommandReceived")。

如果有更好的机制,请评论。我在while循环中将它锁定在ListenCommand中。

以下是代码:

public class LoopingWorkerThread
    {
        /// <summary>
        /// Local main thread for LoopingWorkerThread
        /// </summary>
        private Thread t;
        /// <summary>
        /// Local parameter to identify the LoopingWorkerThread Is On
        /// </summary>
        private bool _IsOn;
        /// <summary>
        /// Local parameter to store command received from user
        /// </summary>
        private int _CommandReceived;
        /// <summary>
        /// Local object to use for locking the LoopingWorker Thread
        /// </summary>
        private object _LockListenCommand = new object();
        /// <summary>
        /// Properties of LoopingWorker Thread Is On
        /// </summary>
        public bool IsOn
        {
            get { return _IsOn; }
            set { _IsOn = value; }
        }
        /// <summary>
        /// Property of storing the command received from user
        /// </summary>
        public int CommandReceived
        {
            get { return _CommandReceived; }
            set { _CommandReceived = value; }
        }
        /// <summary>
        /// Delegate for OnResponse Event Handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void OnResponseHandler(object sender, ResponseArg e);
        /// <summary>
        /// Event of OnResponse
        /// </summary>
        public event OnResponseHandler OnResponse;
        /// <summary>
        /// Constructor of LoopingWorkerThread Class
        /// </summary>
        public LoopingWorkerThread()
        {
            _IsOn = false;
        }
        /// <summary>
        /// Method of LoopingWorkerThread Function
        /// </summary>
        private void ListenCommand()
        {
            lock (_LockListenCommand)
                while (_IsOn)
                {
                    switch (_CommandReceived)
                    {
                        case 0:
                            // Ignore default command
                            break;
                        case 1:
                            FireOnResponse("Received cmd 1, response [Hello One]");
                            break;
                        case 2:
                            FireOnResponse("Received cmd 2, response [Hello Two]");
                            break;
                        default:
                            FireOnResponse("Error. Received unidentified command - " + _CommandReceived.ToString());
                            break;
                    }

                    //Console.WriteLine("ThreadProc: Cmd:[{0}] - Response:{1}", _CommandReceived.ToString(), ReaderResponse);

                    // Reset or Clear the Command Received
                    _CommandReceived = 0;

                    // If the sleep less than 10 millisecond, it always don't catch the 
                    // command received which assigned to 1 or 2. Don't understand, or is there
                    // any better method.
                    **Thread.Sleep(10);**
                }
        }
        /// <summary>
        /// Function of firing response event back to user
        /// </summary>
        /// <param name="message"></param>
        private void FireOnResponse(string message)
        {
            ResponseArg myarg = new ResponseArg(message);
            if (OnResponse != null)
                OnResponse(this, myarg);
        }
        /// <summary>
        /// Method of starting the LoopingWorkerThread
        /// </summary>
        public void Start()
        {
            _IsOn = true;

            FireOnResponse("Main thread: Started.");

            // The constructor for the Thread class requires a ThreadStart 
            // delegate that represents the method to be executed on the 
            // thread.  C# simplifies the creation of this delegate.
            t = new Thread(new ThreadStart(ListenCommand));

            // Start ThreadProc.  Note that on a uniprocessor, the new 
            // thread does not get any processor time until the main thread 
            // is preempted or yields.  Uncomment the Thread.Sleep that 
            // follows t.Start() to see the difference.
            t.Start();

            //Thread.Sleep(0);

            FireOnResponse("Main thread: Call Start().");

        }
        /// <summary>
        /// Method of stopping the LoopingWorkerThread
        /// </summary>
        public void Stop()
        {
            _IsOn = false;
            t.Join();
            //t.Abort();

            FireOnResponse("LoopingWorker Thread is stopped.");
        }
        /// <summary>
        /// Method of sending command to the LoopingWorkerThread
        /// </summary>
        /// <param name="readercmd"></param>
        public void SendCommand(int readercmd)
        {
            _CommandReceived = readercmd;
        }
    }

2 个答案:

答案 0 :(得分:4)

您的代码有效,因为Thread.Sleep produces the necessary memory barrier需要正确阅读_commandReceived。如果删除Thread.Sleep调用,则还会删除隐式内存屏障。显然,这不是一个很好的依赖机制。

更重要的是,你正在以错误的方式解决这个问题。您应该使用的是生产者 - 消费者模式。使用BlockingCollection类非常简单,因为它会在队列为空时阻止Take上的使用者。

public class Example
{
  private BlockingCollection<int> commands = new BlockingCollection<int>();

  public Example()
  {
    var thread = new Thread(Run);
    thread.IsBackground = true;
    thread.Start();
  }

  public void SendCommmand(int command)
  {
    commands.Add(command);
  }

  private void Run()
  {
    while (true)
    {
      int command = commands.Take();
      ProcessCommand(command);      
    }
  }

  private void ProcessCommand(int command)
  {
    // Process the command here.
  }
}

BlockingCollection可用于3.5 Reactive Extensions下载。

答案 1 :(得分:1)

尝试声明变量volatile。有关http://msdn.microsoft.com/en-us/library/x13ttww7.aspx

的更多信息