C#中的队列。数据插入队列但不退出

时间:2016-02-18 05:05:37

标签: c# .net wpf serial-port queue

大家下面是我的代码,正如你在这里看到的那样,我的数据进入队列但是退出有时不会发生,我有点迷失,我会感激任何帮助或评论,下面是我的代码细节分别

                                         ******




 public abstract class Acquisition
    {
        public event EventHandler Starting;
        public event EventHandler Started;
        public event EventHandler Stopping;
        public event EventHandler Stopped;
        public event EventHandler<AcquisitionEventArgs> Acquired;

        private AutoResetEvent stopAcquistion, sendCommand;

        private Thread acquisitionThread;

        private Queue<Command> commandQueue;

        protected virtual void InvokeStarting()
        {
            if (this.Starting != null)
                this.Starting(this, EventArgs.Empty);
        }

        protected virtual void InvokeStarted()
        {
            if (this.Started != null)
                this.Started(this, EventArgs.Empty);
        }

        protected virtual void InvokeStopping()
        {
            if (this.Stopping != null)
                this.Stopping(this, EventArgs.Empty);
        }

        protected virtual void InvokeStopped()
        {
            if (this.Stopped != null)
                this.Stopped(this, EventArgs.Empty);
        }

        public bool IsRunning { get; private set; }

        public Device CurrentDevice { get; private set; }

        private void AcquisitionThread(object parameter)
        {
            var device = parameter as Device;

            if (parameter == null)
                throw new ArgumentException("parameter");

            var handles = new WaitHandle[] {this.stopAcquistion, this.sendCommand};

            bool stop = false;

            this.IsRunning = true;

            while (!stop)
            {
                try
                {
                    switch (WaitHandle.WaitAny(handles, 100))
                    {
                        case 0:
                            stop = true;
                            continue;

                        case 1:
                            lock (this.commandQueue)
                            {
                                if (this.commandQueue.Count > 0 )
                                    this.TransmitCommand(device, this.commandQueue.Dequeue());

                            }
                            break;

                        default:
                            break;
                    }

                    if (!this.Acquire(device))
                        break;
                }
                catch (Exception e)
                {
                    Trace.WriteLine(e);

                    break;
                }
            }

            Disposable.SafeDispose(ref device);

            Disposable.SafeDispose(ref stopAcquistion);

            this.IsRunning = false;
        }

        public void EnqueueCommand(Command command)
        {

            if(this.commandQueue == null)
                return;

            lock (this.commandQueue)
                this.commandQueue.Enqueue(command);

            this.sendCommand.Set();
        }

        protected virtual void TransmitCommand(Device device, Command command)
        {
        }

        protected virtual bool Acquire(Device d)
        {
            return false;
        }

        public void Start(Device device)
        {
            this.InvokeStarting();

            this.CurrentDevice = device;

            this.acquisitionThread = new Thread(AcquisitionThread);
            this.acquisitionThread.Start(device);

            this.stopAcquistion = new AutoResetEvent(false);
            this.sendCommand = new AutoResetEvent(false);

            this.commandQueue = new Queue<Command>();

            this.InvokeStarted();
        }

        protected virtual void InvokeAquired(byte[] bytes, int count)
        {
            if (this.Acquired != null)
                this.Acquired(this, new AcquisitionEventArgs
                                        {
                                            Bytes = bytes,
                                            Count = count
                                        });
        }

        public void Stop()
        {
            if (this.stopAcquistion == null)
                return;

            this.InvokeStopping();

            this.stopAcquistion.Set();

            this.InvokeStopped();
        }
    }
}



                                  ********* 

我将几个命令传递到我的队列,基本上他们通过串口

AcquisitionLoop.Luminaires.EnqueueCommand(new SetLumDimLevelCommand(new LumDimLevelInfo(Name, 100, DeviceTypes, 1))) 

//这是我的命令,转到上面的代码。 在上面的代码中

EnqueueCommand(Command command)
{
        if(this.commandQueue == null)
            return;

        lock (this.commandQueue)    // queue gets lagged and the count keeps increseing 
            this.commandQueue.Enqueue(command);

        this.sendCommand.Set();
}

1 个答案:

答案 0 :(得分:0)

这是一个有效的代码,其中包含用于解释我的更改的注释

void Main()
{
    var a = new Acquisition();
    a.Start(new Device());

    // here is a thread inserting a hundred command into the queue at a small interval for testing
    Thread t = new Thread(() => {
        for(int i = 0; i < 100; i++)
        {
            a.EnqueueCommand(new Command{Id = i});
            Thread.Sleep(50);
        }
    });
    t.Start();

    // lets wait some time before we terminate the program to see the queue working the Acquisition working through the queue
    System.Threading.Thread.Sleep(10000);

    // and we kill the Acquisition now
    a.Stop();
}

// Define other methods and classes here

public class Acquisition
    {
        public event EventHandler Starting;
        public event EventHandler Started;
        public event EventHandler Stopping;
        public event EventHandler Stopped;

        // changed to the generic EventArgs for the purpose of testing
        public event EventHandler<EventArgs> Acquired;

        private AutoResetEvent stopAcquistion;

        private Thread acquisitionThread;

        // using a multi-threaded queue is better here in your scenario
        private ConcurrentQueue<Command> commandQueue;

        protected virtual void InvokeStarting()
        {
            Console.WriteLine("InvokeStarting");
            if (this.Starting != null)
                this.Starting(this, EventArgs.Empty);
        }

        protected virtual void InvokeStarted()
        {
            Console.WriteLine("InvokeStarted");
            if (this.Started != null)
                this.Started(this, EventArgs.Empty);
        }

        protected virtual void InvokeStopping()
        {
            Console.WriteLine("InvokeStopping");
            if (this.Stopping != null)
                this.Stopping(this, EventArgs.Empty);
        }

        protected virtual void InvokeStopped()
        {
            Console.WriteLine("InvokeStopped");
            if (this.Stopped != null)
                this.Stopped(this, EventArgs.Empty);
        }

        public bool IsRunning { get; private set; }

        public object CurrentDevice { get; private set; }

        private void AcquisitionThread(object parameter)
        {
            var device = parameter as Device;

            if (parameter == null)
                throw new ArgumentException("parameter");

            var handles = new WaitHandle[] {this.stopAcquistion};

            bool stop = false;

            this.IsRunning = true;

            while (!stop)
            {
                try
                {
                    if (!commandQueue.IsEmpty)
                    {
                        Command cmd;
                        if(commandQueue.TryDequeue(out cmd))
                        {
                            TransmitCommand(device, cmd);
                        }
                    }

                    if(stopAcquistion.WaitOne(100))
                    {
                       stop = true;
                       continue;
                    }

                    if (!this.Acquire(device))
                        break;
                }
                catch (Exception e)
                {
                    Trace.WriteLine(e);

                    break;
                }
            }


            device = null;
            stopAcquistion = null;

            this.IsRunning = false;
        }

        public void EnqueueCommand(Command command)
        {
            Console.WriteLine(String.Format("EnqueueCommand: {0}", command.Id));
            if(this.commandQueue == null)
                return;

            lock (this.commandQueue)
                this.commandQueue.Enqueue(command);

            //this.sendCommand.Set();
        }

        protected virtual void TransmitCommand(object device, Command command)
        {
            Console.WriteLine(String.Format("TransmitCommand: {0}", command.Id));
        }

        protected virtual bool Acquire(Device d)
        {
            return true;
        }

        public void Start(Device device)
        {
            this.InvokeStarting();

            this.CurrentDevice = device;

            this.acquisitionThread = new Thread(AcquisitionThread);
            this.acquisitionThread.Start(device);

            this.stopAcquistion = new AutoResetEvent(false);
            // using a multi-threaded queue is better here in your scenario
            this.commandQueue = new ConcurrentQueue<Command>();

            this.InvokeStarted();
        }

        protected virtual void InvokeAquired(byte[] bytes, int count)
        {
            Console.WriteLine("InvokeAquired");
            if (this.Acquired != null)
                this.Acquired(this, new EventArgs());
        }

        public void Stop()
        {
            if (this.stopAcquistion == null)
                return;

            this.InvokeStopping();
            this.stopAcquistion.Set();
            this.InvokeStopped();
        }
    }
// I needed to implement an empty Command, and Device to make the code works in my example
public class Command{ public int Id {get;set;} }
public class Device{}