大家下面是我的代码,正如你在这里看到的那样,我的数据进入队列但是退出有时不会发生,我有点迷失,我会感激任何帮助或评论,下面是我的代码细节分别
******
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();
}
答案 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{}