I am having trouble with SerialPort.DataReceived event being blocked by ShowDialog from MainWindow. Originally, the code worked as follows:
Printer connected to COM port using Windows Print Driver for operation. To check status, I must "move" windows printer COM port to COM1, and connect directly to the printer via SerialPort and send it a certain array of bytes. The printer will answer back >>LOW STOCK<< if out of paper or >>READY<< if status OK. I receive this through the serialport.datareceived event that I set up when switching the com port. If I get >>LOW STOCK<<, I continue to poll the printer over the serial port every 2 seconds.
public class PrintController
{
private PrintMonitor DefaultPrintMonitor;
public Printcontroller()
{
Initialize();
}
private void Initialize()
{
// Some code here to determine which printer type to load monitor for
DefaultPrintMonitor = new PrintMonitor();
}
}
And the Print Monitor:
public class PrintMonitor
{
private SerialPort Port;
private TimeoutManager TimeoutQueue = new TimeoutQueue();
private readonly char[] PrinterStatusCommand = new char[7] { ... The printers report status command ...};
public PrintMonitor() {}
public void StartPrintMonitor()
{
Thread thread = new Thread(new ThreadStart(RefreshPrintQueue))
{
IsBackground = true
};
thread.Start();
}
private void RefreshPrintQueue()
{
// This checks the Printer's Queue for any jobs remaining
// If the number of jobs = 0, all data has been transferred to the printer
// and we can switch the COM port so the printer can be polled for it's status
// Code omitted for brevity
if (jobs.Count() > 0)
{
// This will wait 1000ms and execute the method RefreshPrintQueue
TimeoutQueue.AddTimeout(RefreshPrintQueue, 1000);
}
else
{
TimeoutQueue.AddTimeout(GetStatus, 500);
}
}
private void GetStatus()
{
// Connect windows print driver to COM1
SetWindowsPrintDriver("COM1");
// Connect to printer using new SerialPort
ConnectSerialPrintDriver();
// Poll the printer over new SerialPort connection
QueryPrinterStatus();
}
private void ConnectSerialPrintDriver()
{
//Create new serial port to Port, and open
Port.DataReceived += Port_DataReceived;
}
private void QueryPrinterStatus()
{
byte[] send = Encoding.ASCII.GetBytes(PrinterStatusCommand);
Port.Write(send, 0, send.Length);
TimeoutQueue.AddTimeout(QueryPrinterStatus, 2000);
}
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(100);
SerialPort p = sender as SerialPort;
string recv = p.ReadExisting().Trim();
if (recv.Contains(">>READY<<"))
{
// Stop Polling loop
TimeoutQueue.ClearAllTimeouts();
DisconnectSerialPrintDriver();
// Raises event to Main to close ShowDialog
}
else
{
// Raises event to Main to open ShowDialog
}
}
private void DisconnectSerialPrintDriver()
{
// Closes/Disconnects serial port from printer
// unsubscribes event listener
// Sets Port to null and connects windows print driver back to printers COM port
// Ready to accept print jobs again
}
Believe it or not, this works very well. When the paper is reloaded in the printer, the dialog window showing the paper out message is dismissed.
However, I recently had to make a change to the print controller to make it a static class. Now, when I open the dialog window at Main, the Port_DataReceived event stops firing. The polling of the printer continues, and the responses just seem to back up until the dialog window is manually dismissed, and then I get one more dataReceived event with the results of all the polling that went on while showing the dialog window.
Can anyone tell me what could be happening here?