I'm developing an application to control cafeteria consumption for my company. Basically each employee has a badge id with a barcode, and they are entitled to a free meal every day. The application will scan the badge and log each employees' meals. It will run on a Motorola MK4000 device, which has an integrated scanner and runs on Windows CE.
I've got an issue with the device scanner. I can get it to run and scan fine, but if it stays idle for a few minutes, it goes to "Waiting" status, the laser turns off, and doesn't come back on. I've tried monitoring the status and starting a new read when it changes to that status, but then it just keeps scanning false reads indefinitely.
Can you guys help me figure out what im doing wrong?
This is the class I'm using for the scanner functionality. It wasn't developed by me, but its begin used for other applications on the same device (I made a few changes to it, mostly on the error messages).
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace MK4000
{
class BarCode
{
#region Fields
private Symbol.Barcode.Reader myReader = null;
private Symbol.Barcode.ReaderData myReaderData = null;
private System.EventHandler myReadNotifyHandler = null;
private System.EventHandler myStatusNotifyHandler = null;
#endregion Fields
#region Properties
/// <summary>
/// Provides the access to the Symbol.Barcode.Reader reference.
/// The user can use this reference for his additional Reader - related operations.
/// </summary>
public Symbol.Barcode.Reader Reader
{
get
{
return myReader;
}
}
public String ErrorMessage
{
get
{
return "Error";
}
}
#endregion Properties
#region Methods
/// <summary>
/// Attach a ReadNotify handler.
/// </summary>
public void AttachReadNotify(System.EventHandler ReadNotifyHandler)
{
// If we have a reader
if (myReader != null)
{
// Attach the read notification handler.
myReader.ReadNotify += ReadNotifyHandler;
myReadNotifyHandler = ReadNotifyHandler;
}
}
/// <summary>
/// Attach a StatusNotify handler.
/// </summary>
public void AttachStatusNotify(System.EventHandler StatusNotifyHandler)
{
// If we have a reader
if (myReader != null)
{
// Attach status notification handler.
myReader.StatusNotify += StatusNotifyHandler;
myStatusNotifyHandler = StatusNotifyHandler;
}
}
/// <summary>
/// Detach the ReadNotify handler.
/// </summary>
public void DetachReadNotify()
{
if ((myReader != null) && (myReadNotifyHandler != null))
{
// Detach the read notification handler.
myReader.ReadNotify -= myReadNotifyHandler;
myReadNotifyHandler = null;
}
}
/// <summary>
/// Detach a StatusNotify handler.
/// </summary>
public void DetachStatusNotify()
{
// If we have a reader registered for receiving the status notifications
if ((myReader != null) && (myStatusNotifyHandler != null))
{
// Detach the status notification handler.
myReader.StatusNotify -= myStatusNotifyHandler;
myStatusNotifyHandler = null;
}
}
/// <summary>
/// Initialize the reader.
/// </summary>
public bool InitReader()
{
// If the reader is already initialized then fail the initialization.
if (myReader != null)
{
return false;
}
else // Else initialize the reader.
{
try
{
// Get the device selected by the user.
Symbol.Generic.Device MyDevice =
Symbol.StandardForms.SelectDevice.Select(
Symbol.Barcode.Device.Title,
Symbol.Barcode.Device.AvailableDevices);
if (MyDevice == null)
{
MessageBox.Show(ErrorMessage);
return false;
}
// Create the reader, based on selected device.
myReader = new Symbol.Barcode.Reader(MyDevice);
// Create the reader data.
myReaderData = new Symbol.Barcode.ReaderData(
Symbol.Barcode.ReaderDataTypes.Text,
Symbol.Barcode.ReaderDataLengths.MaximumLabel);
// Enable the Reader.
myReader.Actions.Enable();
// In this sample, we are setting the aim type to trigger.
switch (myReader.ReaderParameters.ReaderType)
{
case Symbol.Barcode.READER_TYPE.READER_TYPE_IMAGER:
myReader.ReaderParameters.ReaderSpecific.ImagerSpecific.AimType = Symbol.Barcode.AIM_TYPE.AIM_TYPE_TRIGGER;
//myReader.Parameters.Feedback.Success.BeepTime = 0;
break;
case Symbol.Barcode.READER_TYPE.READER_TYPE_LASER:
myReader.ReaderParameters.ReaderSpecific.LaserSpecific.AimType = Symbol.Barcode.AIM_TYPE.AIM_TYPE_TRIGGER;
break;
case Symbol.Barcode.READER_TYPE.READER_TYPE_CONTACT:
// AimType is not supported by the contact readers.
break;
}
myReader.Actions.SetParameters();
}
catch (Symbol.Exceptions.OperationFailureException ex)
{
MessageBox.Show(ex.Message);
return false;
}
catch (Symbol.Exceptions.InvalidRequestException ex)
{
MessageBox.Show(ex.Message);
return false;
}
catch (Symbol.Exceptions.InvalidIndexerException ex)
{
MessageBox.Show(ex.Message);
return false;
};
return true;
}
}
/// <summary>
/// Start a read on the reader.
/// </summary>
public void StartRead(bool toggleSoftTrigger)
{
// If we have both a reader and a reader data
if ((myReader != null) &&
(myReaderData != null))
try
{
if (!myReaderData.IsPending)
{
// Submit a read.
myReader.Actions.Read(myReaderData);
if (toggleSoftTrigger && myReader.Info.SoftTrigger == false)
{
myReader.Info.SoftTrigger = true;
}
}
}
catch (Symbol.Exceptions.OperationFailureException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidRequestException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidIndexerException ex)
{
MessageBox.Show(ex.Message);
};
}
/// <summary>
/// Stop all reads on the reader.
/// </summary>
public void StopRead()
{
//If we have a reader
if (myReader != null)
{
try
{
// Flush (Cancel all pending reads).
if (myReader.Info.SoftTrigger == true)
{
myReader.Info.SoftTrigger = false;
}
myReader.Actions.Flush();
}
catch (Symbol.Exceptions.OperationFailureException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidRequestException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidIndexerException ex)
{
MessageBox.Show(ex.Message);
};
}
}
/// <summary>
/// Stop reading and disable/close the reader.
/// </summary>
public void TermReader()
{
// If we have a reader
if (myReader != null)
{
try
{
// stop all the notifications.
StopRead();
//Detach all the notification handler if the user has not done it already.
DetachReadNotify();
DetachStatusNotify();
// Disable the reader.
myReader.Actions.Disable();
// Free it up.
myReader.Dispose();
// Make the reference null.
myReader = null;
}
catch (Symbol.Exceptions.OperationFailureException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidRequestException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidIndexerException ex)
{
MessageBox.Show(ex.Message);
};
}
// After disposing the reader, dispose the reader data.
if (myReaderData != null)
{
try
{
// Free it up.
myReaderData.Dispose();
// Make the reference null.
myReaderData = null;
}
catch (Symbol.Exceptions.OperationFailureException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidRequestException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidIndexerException ex)
{
MessageBox.Show(ex.Message);
};
}
}
#endregion Methods
}
}
And this is the code for the actual form:
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace MK4000
{
public partial class Form1 : Form
{
private bool isReaderInitiated;
private BarCode myScanner;
private EventHandler myStatusNotifyHandler = null;
private EventHandler myReadNotifyHandler = null;
private String MacAddress = "00-00-00-00-00-00";
private String strIPAddress = "000.000.000.000";
private String version = "0.0.0.1";
public static int TaskbarHeight = Screen.PrimaryScreen.Bounds.Height - Screen.PrimaryScreen.WorkingArea.Height;
private int counter = 0;
private int itemLimit = 10;
public String ErrorMessage
{
get
{
return "Error";
}
}
public Form1()
{
InitializeComponent();
this.Width = Screen.PrimaryScreen.Bounds.Width;
this.Height = Screen.PrimaryScreen.Bounds.Height - TaskbarHeight;
this.FormBorderStyle = FormBorderStyle.None;
this.ControlBox = false;
this.MinimizeBox = false;
this.EmpID.Visible = false;
this.EmpName.Visible = false;
this.messageLabel.Visible = false;
this.lblCounter.Text = counter.ToString();
this.lblCounter.Visible = false;
this.statusBar1.Text = "Initializing.. Reticulating Splines " + MacAddress + " | " + strIPAddress + " | " + version;
this.listView1.View = View.Details;
this.listView1.Columns.Add("EmployeeID", 150, HorizontalAlignment.Left);
this.listView1.Columns.Add("EmployeeName", 330, HorizontalAlignment.Left);
this.listView1.Columns.Add("Time", 250, HorizontalAlignment.Left);
this.Closing += new CancelEventHandler(Form1_OnClosing);
this.myScanner = new BarCode();
this.isReaderInitiated = this.myScanner.InitReader();
if (!(this.isReaderInitiated))// If the reader has not been initialized
{
// Display a message & exit the application.
MessageBox.Show(ErrorMessage);
Application.Exit();
}
else // If the reader has been initialized
{
// Attach a status natification handler.
myScanner.AttachStatusNotify(myScanner_StatusNotify);
// Start a read operation & attach a handler.
myScanner.StartRead(true);
myScanner.AttachReadNotify(myScanner_ReadNotify);
}
}
private void myScanner_ReadNotify(object Sender, EventArgs e)
{
// Get ReaderData
Symbol.Barcode.ReaderData TheReaderData = this.myScanner.Reader.GetNextReaderData();
processData(TheReaderData.ToString());
this.myScanner.StopRead();
System.Threading.Thread.Sleep(1000);
this.myScanner.StartRead(true);
}
private void processData(string readerData)
{
string EmployeeName = "";
string EmployeeID = readerData;
hideMessage();
//This will query the employee database and proceed if employee exists, right now i just give it a random name
EmployeeName = "John Doe";
if (EmployeeName != "")
{
addToList(EmployeeID, EmployeeName);
counter += 1;
this.lblCounter.Text = counter.ToString();
this.EmpID.Visible = true
this.EmpName.Visible = true
this.lblCounter.Visible = true;
showMessage("Thank You!", System.Drawing.Color.LimeGreen);
}
}
private void showMessage(string messageText, System.Drawing.Color messageColor)
{
this.messageLabel.Text = messageText;
this.messageLabel.BackColor = messageColor;
this.messageLabel.Visible = true;
}
private void hideMessage()
{
this.messageLabel.Text = "";
this.messageLabel.BackColor = System.Drawing.Color.Black;
this.messageLabel.Visible = false;
}
private void addToList(string EmployeeID, string EmployeeName)
{
if (this.listView1.Items.Count >= itemLimit)
{
this.listView1.Items.RemoveAt(0);
}
ListViewItem item = new ListViewItem(EmployeeID);
//item.Text = EmployeeID;
item.SubItems.Add(EmployeeName);
item.SubItems.Add(DateTime.Now.ToString());
this.listView1.Items.Add(item);
this.listView1.Refresh();
}
private void myScanner_StatusNotify(object Sender, EventArgs e)
{
// Get ReaderData
Symbol.Barcode.BarcodeStatus TheStatusData = this.myScanner.Reader.GetNextStatus();
switch (TheStatusData.State)
{
case Symbol.Barcode.States.IDLE:
this.statusBar1.Text = "Idle - Scan ID Barcode " + MacAddress + " | " + strIPAddress + " | " + version;
break;
case Symbol.Barcode.States.READY:
this.statusBar1.Text = "Ready - Scan ID Barcode " + MacAddress + " | " + strIPAddress + " | " + version;
break;
case Symbol.Barcode.States.WAITING:
//this.myScanner.StopRead();
//this.myScanner.StartRead(true);
this.statusBar1.Text = "Waiting- Scan ID Barcode " + MacAddress + " | " + strIPAddress + " | " + version;
break;
default:
this.statusBar1.Text = TheStatusData.Text + " " + MacAddress + " | " + strIPAddress + " | " + version;
break;
}
}
private void Form1_OnClosing(object Sender, EventArgs e)
{
if (isReaderInitiated)
{
myScanner.DetachReadNotify();
myScanner.DetachStatusNotify();
myScanner.TermReader();
}
}
private void pictureBox1_Click(object sender, EventArgs e)
{
this.Close();
}
private void pictureBox2_Click(object sender, EventArgs e)
{
this.myScanner.StopRead();
this.myScanner.StartRead(true);
}
}
}
This is still a work in progress, mind you, so there is some functionality missing, but I want to have the scanner workingfull before moving forward. Any help will be greatly appreciated, thank you.
Ok, I figured out that the scanner goes into a cycle of switching between Idle and Waiting status, this is why my StatusNotify event handler was making the scanner laser turn on and off repeatedly.
I solved it by saving the previous status, and only restarting the scanner when the previous status is not one of those two.
case Symbol.Barcode.States.WAITING:
if (lastScannerStatus != "WAITING" && lastScannerStatus != "INIT" && lastScannerStatus != "IDLE")
{
this.myScanner.StopRead();
this.myScanner.StartRead(true);
}
this.statusBar1.Text = "Waiting- Scan ID Barcode " + MacAddress + " | " + strIPAddress + " | " + version;
break;
Related
I've used in the past RabbitMq as MessageQueue and it was really simple to have an event fired when a message has been received.
I've looked at the .NET sources provided with IBM installer but I've found a not good way to handle it. Looking at the sample SimpleSubscribe it does such a thing to pool
// getting messages continuously
for (int i = 1; i <= numberOfMsgs; i++)
{
// creating a message object
message = new MQMessage();
try
{
topic.Get(message);
Console.WriteLine("Message " + i + " got = " + message.ReadString(message.MessageLength));
message.ClearMessage();
}
catch (MQException mqe)
{
if (mqe.ReasonCode == 2033)
{
++time;
--i;
Console.WriteLine("No message available");
Thread.Sleep(1000);
//waiting for 10sec
if (time > 10)
{
Console.WriteLine("Timeout : No message available");
break;
}
continue;
}
else
{
Console.WriteLine("MQException caught: {0} - {1}", mqe.ReasonCode, mqe.Message);
}
}
}
where the number of numberOfMsgs is an integer passed as an argument. If I pass -1 it probably will pool at the infinite but I think it's not a good approach. This leads me to pool the queue at a specific interval then probably will spin a thread at 100% I don't put a Thread.Sleep
Does anyone have a better approach?
You should use "MQGET with Wait" option rather than use polling. The MQGET call will wait for a message to arrive and return immediately when it receives a message otherwise it will wait for "x" milliseconds.
Here is a simple working C# MQ program:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using IBM.WMQ;
/// <summary> Program Name
/// MQTest62
///
/// Description
/// This C# class will connect to a remote queue manager
/// and get messages from a queue using a managed .NET environment.
///
/// Sample Command Line Parameters
/// -h 127.0.0.1 -p 1415 -c TEST.CHL -m MQWT1 -q TEST.Q1 -u tester -x mypwd
/// </summary>
/// <author> Roger Lacroix
/// </author>
namespace MQTest62
{
public class MQTest62
{
private Hashtable inParms = null;
private Hashtable qMgrProp = null;
private System.String qManager;
private System.String inputQName;
/*
* The constructor
*/
public MQTest62()
: base()
{
}
/// <summary> Make sure the required parameters are present.</summary>
/// <returns> true/false
/// </returns>
private bool allParamsPresent()
{
bool b = inParms.ContainsKey("-h") && inParms.ContainsKey("-p") &&
inParms.ContainsKey("-c") && inParms.ContainsKey("-m") &&
inParms.ContainsKey("-q");
if (b)
{
try
{
System.Int32.Parse((System.String)inParms["-p"]);
}
catch (System.FormatException e)
{
b = false;
}
}
return b;
}
/// <summary> Extract the command-line parameters and initialize the MQ variables.</summary>
/// <param name="args">
/// </param>
/// <throws> IllegalArgumentException </throws>
private void init(System.String[] args)
{
inParms = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable(14));
if (args.Length > 0 && (args.Length % 2) == 0)
{
for (int i = 0; i < args.Length; i += 2)
{
inParms[args[i]] = args[i + 1];
}
}
else
{
throw new System.ArgumentException();
}
if (allParamsPresent())
{
qManager = ((System.String)inParms["-m"]);
inputQName = ((System.String)inParms["-q"]);
qMgrProp = new Hashtable();
qMgrProp.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
qMgrProp.Add(MQC.HOST_NAME_PROPERTY, ((System.String)inParms["-h"]));
qMgrProp.Add(MQC.CHANNEL_PROPERTY, ((System.String)inParms["-c"]));
try
{
qMgrProp.Add(MQC.PORT_PROPERTY, System.Int32.Parse((System.String)inParms["-p"]));
}
catch (System.FormatException e)
{
qMgrProp.Add(MQC.PORT_PROPERTY, 1414);
}
if (inParms.ContainsKey("-u"))
qMgrProp.Add(MQC.USER_ID_PROPERTY, ((System.String)inParms["-u"]));
if (inParms.ContainsKey("-x"))
qMgrProp.Add(MQC.PASSWORD_PROPERTY, ((System.String)inParms["-x"]));
System.Console.Out.WriteLine("MQTest62:");
Console.WriteLine(" QMgrName ='{0}'", qManager);
Console.WriteLine(" Output QName ='{0}'", inputQName);
System.Console.Out.WriteLine("QMgr Property values:");
foreach (DictionaryEntry de in qMgrProp)
{
Console.WriteLine(" {0} = '{1}'", de.Key, de.Value);
}
}
else
{
throw new System.ArgumentException();
}
}
/// <summary> Connect, open queue, read (browse) a message, close queue and disconnect. </summary>
///
private void testReceive()
{
MQQueueManager qMgr = null;
MQQueue inQ = null;
int openOptions = MQC.MQOO_INPUT_AS_Q_DEF + MQC.MQOO_FAIL_IF_QUIESCING;
try
{
qMgr = new MQQueueManager(qManager, qMgrProp);
System.Console.Out.WriteLine("MQTest62 successfully connected to " + qManager);
inQ = qMgr.AccessQueue(inputQName, openOptions);
System.Console.Out.WriteLine("MQTest62 successfully opened " + inputQName);
testLoop(inQ);
}
catch (MQException mqex)
{
System.Console.Out.WriteLine("MQTest62 cc=" + mqex.CompletionCode + " : rc=" + mqex.ReasonCode);
}
catch (System.IO.IOException ioex)
{
System.Console.Out.WriteLine("MQTest62 ioex=" + ioex);
}
finally
{
try
{
if (inQ != null)
inQ.Close();
System.Console.Out.WriteLine("MQTest62 closed: " + inputQName);
}
catch (MQException mqex)
{
System.Console.Out.WriteLine("MQTest62 cc=" + mqex.CompletionCode + " : rc=" + mqex.ReasonCode);
}
try
{
if (qMgr != null)
qMgr.Disconnect();
System.Console.Out.WriteLine("MQTest62 disconnected from " + qManager);
}
catch (MQException mqex)
{
System.Console.Out.WriteLine("MQTest62 cc=" + mqex.CompletionCode + " : rc=" + mqex.ReasonCode);
}
}
}
private void testLoop(MQQueue inQ)
{
bool flag = true;
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.Options |= MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING;
gmo.WaitInterval = 2500; // 2.5 seconds wait time or use MQC.MQEI_UNLIMITED to wait forever
MQMessage msg = null;
while (flag)
{
try
{
msg = new MQMessage();
inQ.Get(msg, gmo);
System.Console.Out.WriteLine("Message Data: " + msg.ReadString(msg.MessageLength));
}
catch (MQException mqex)
{
System.Console.Out.WriteLine("MQTest62 CC=" + mqex.CompletionCode + " : RC=" + mqex.ReasonCode);
if (mqex.Reason == MQC.MQRC_NO_MSG_AVAILABLE)
{
// no meesage - life is good - loop again
}
else
{
flag = false; // severe error - time to exit
}
}
catch (System.IO.IOException ioex)
{
System.Console.Out.WriteLine("MQTest62 ioex=" + ioex);
}
}
}
/// <summary> main line</summary>
/// <param name="args">
/// </param>
// [STAThread]
public static void Main(System.String[] args)
{
MQTest62 write = new MQTest62();
try
{
write.init(args);
write.testReceive();
}
catch (System.ArgumentException e)
{
System.Console.Out.WriteLine("Usage: MQTest62 -h host -p port -c channel -m QueueManagerName -q QueueName [-u userID] [-x passwd]");
System.Environment.Exit(1);
}
catch (MQException e)
{
System.Console.Out.WriteLine(e);
System.Environment.Exit(1);
}
System.Environment.Exit(0);
}
}
}
I having a little issue reading data from Nave32 Flight Controller, I'm able to send data to the card using the SerialDevice class but when the LoadAsync Method is call and there is no more data to read the app hung and does not move forward, there is not exception during the execution of the process. I look at the app state and there is a bunch a task block and I'm not sure why. See image below
UPDATE
Firmware source code is here
here is my example code
namespace Apps.Receiver
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.dataRecived.Text = DateTime.Now.ToString();
}
private async Task readAsync(SerialDevice serialPort)
{
string data = string.Empty;
using (var dataReaderObject = new DataReader(serialPort.InputStream))
{
try
{
dataReaderObject.InputStreamOptions = InputStreamOptions.None;
var hasData = true;
while (hasData)
{
var bytesRead = await dataReaderObject.LoadAsync(serialPort.DataBits);
if (bytesRead > 0)
data += dataReaderObject.ReadString(bytesRead);
else
hasData = false;
}
}
catch (Exception ex)
{
status.Text = "reading data fail: " + ex.Message;
closeDevice(serialPort);
}
}
dataRecived.Text = data;
}
private async void sendData_Click(object sender, RoutedEventArgs e)
{
var serialPort = await getSerialDevice("COM3");
if (dataToSend.Text.Length != 0)
{
using (var dataWriteObject = new DataWriter(serialPort.OutputStream))
{
try
{
if (dataToSend.Text.Equals("#", StringComparison.CurrentCultureIgnoreCase))
dataWriteObject.WriteString(dataToSend.Text);
else
dataWriteObject.WriteString(dataToSend.Text + "\n");
var bytesWritten = await dataWriteObject.StoreAsync();
if (bytesWritten > 0)
{
status.Text = dataToSend.Text + ", ";
status.Text += "bytes written successfully!";
}
await readAsync(serialPort);
}
catch (Exception ex)
{
status.Text = "writing data fail: " + ex.Message;
}
}
closeDevice(serialPort);
}
else
{
status.Text = "Enter the text you want to write and then click on 'WRITE'";
}
}
private void closeDevice(SerialDevice device)
{
device.Dispose();
device = null;
}
private async Task<SerialDevice> getSerialDevice(string portName)
{
var aqs = SerialDevice.GetDeviceSelector("COM3");
var devices = await DeviceInformation.FindAllAsync(aqs);
if (devices.Count == 0)
throw new Exception("Unablet to connect to device");
var serialPort = await SerialDevice.FromIdAsync(devices[0].Id);
if (serialPort == null)
throw new Exception("Unablet to Open to port " + portName);
serialPort.BaudRate = 115200;
serialPort.DataBits = 8;
return serialPort;
}
}
}
See this example, try if it helps doing it like this:
await reader.LoadAsync(8192);
while (reader.UnconsumedBufferLength > 0)
{
strBuilder.Append(reader.ReadString(reader.UnconsumedBufferLength));
await reader.LoadAsync(8192);
}
I have a question that I cant come up with a solution for. Its About my application on a motorola MC3190-G Handheld Application on wm 6.5 and Compact Framework 2.0
After implementation of the Symbol Package for using the scanner trigger inside my application, I get the following error everytime I close my application / or a form which has the scanner enabled:
(Even if I never received data from scanning)
I searched for a solution on stackoverflow and other sites with no solutions to fix it.
I am new to mobile application development. I try and catched everything but the error seem to can't be catched with exceptiontype "exception".
sorry for the poor english.
Error:
NullReferenceException
at MainForm.SymbolReader_ReadNotifiy() at Task.Invoke()
at System.Windows.Forms.Control._InvokeAll() at
System.Windows.Forms.Control.WinProc()
Informations:
Motorola EMDK 2.6
Device: MC3190-G
Sourcecode:
Scanner.cs
namespace MyScann
{
/// <summary>
/// Summary description for Scanner.
/// </summary>
public class Scanner
{
public static Symbol.Barcode.Reader SymbolReader = null;
public static Symbol.Barcode.ReaderData SymbolReaderData = null;
public static System.EventHandler SymbolEventHandler = null;
public static DataSet CodeDataSet;
//public static Utils.Sound ReadErrorSound;
public static bool ScannerEnabled = false;
public static void ActivateScanner()
{
// If we have both a reader and a reader-data Object
if ( Scanner.SymbolReader != null &&
Scanner.SymbolReaderData != null &&
! Scanner.SymbolReaderData.IsPending )
{
// Submit 'Read'
try
{
Scanner.SymbolReader.Actions.Read(Scanner.SymbolReaderData);
}
catch (Exception err)
{
MessageBox.Show(err.Message);
if ( err.InnerException != null )
MessageBox.Show(err.InnerException.Message);
}
}
}
public static void DeactivateScanner()
{
// If we have both a reader and a reader-data Object
if ( Scanner.SymbolReader != null &&
Scanner.SymbolReaderData != null &&
Scanner.SymbolReaderData.IsPending )
{
// Submit 'CancelRead'
try
{
Scanner.SymbolReader.Actions.CancelRead(Scanner.SymbolReaderData);
}
catch (Exception err)
{
MessageBox.Show(err.Message);
if ( err.InnerException != null )
MessageBox.Show(err.InnerException.Message);
}
}
}
/// <summary>
/// Initialize the reader.
/// </summary>
/// <returns>False if an error accurs</returns>
public static bool InitSymbolReader()
{
// If reader is already present then fail initialize
if ( SymbolReader != null )
{
return false;
}
// Create new reader, first available reader will be used.
SymbolReader = new Symbol.Barcode.Reader();
// Create reader data
SymbolReaderData = new Symbol.Barcode.ReaderData(
Symbol.Barcode.ReaderDataTypes.Text,
Symbol.Barcode.ReaderDataLengths.DefaultText);
// set scanner read error sound
//ReadErrorSound = new Utils.Sound(ErrorSound);
return true;
}
/// <summary>
/// Stop reading and disable/close reader
/// </summary>
public static void DeinitSymbolReader()
{
try
{
// If we have a reader
if ( SymbolReader != null )
{
//Cancel Incoming Requests
SymbolReader.Actions.Flush();
// Disable the reader
SymbolReader.Actions.Disable();
// Free it up
SymbolReader.Dispose();
// Indicate we no longer have one
SymbolReader = null;
}
// If we have a reader data
if ( SymbolReaderData != null )
{
// Free it up
SymbolReaderData.Dispose();
// Indicate we no longer have one
SymbolReaderData = null;
}
if(SymbolEventHandler!=null){
//SymbolEventHandler(this,null);
SymbolEventHandler = null;
}
}
catch (Exception e){MessageBox.Show(e.StackTrace.ToString());
}
}
/// <summary>
/// Enable most barcode type with no limitation on length
/// </summary>
public static void OpenAllBarcodes()
{
SymbolReader.Decoders.CODABAR.Enabled = true;
SymbolReader.Decoders.CODABAR.MinimumLength = 0;
SymbolReader.Decoders.CODABAR.MaximumLength = 0;
SymbolReader.Decoders.CODE11.Enabled = true;
SymbolReader.Decoders.CODE11.MinimumLength = 0;
SymbolReader.Decoders.CODE11.MaximumLength = 0;
SymbolReader.Decoders.CODE39.Enabled = true;
SymbolReader.Decoders.CODE39.MinimumLength = 0;
SymbolReader.Decoders.CODE39.MaximumLength = 0;
SymbolReader.Decoders.CODE93.Enabled = true;
SymbolReader.Decoders.CODE93.MinimumLength = 0;
SymbolReader.Decoders.CODE93.MaximumLength = 0;
SymbolReader.Decoders.CODE128.Enabled = true;
SymbolReader.Decoders.CODE128.MinimumLength = 0;
SymbolReader.Decoders.CODE128.MaximumLength = 0;
SymbolReader.Decoders.DATAMATRIX.Enabled = true;
SymbolReader.Decoders.DATAMATRIX.MinimumLength = 0;
SymbolReader.Decoders.DATAMATRIX.MaximumLength = 0;
SymbolReader.Decoders.D2OF5.Enabled = true;
SymbolReader.Decoders.D2OF5.MinimumLength = 0;
SymbolReader.Decoders.D2OF5.MaximumLength = 0;
SymbolReader.Decoders.I2OF5.Enabled = true;
SymbolReader.Decoders.I2OF5.MinimumLength = 0;
SymbolReader.Decoders.I2OF5.MaximumLength = 0;
/*
SymbolReader.Decoders.EAN13.Enabled = true;
SymbolReader.Decoders.EAN13.MinimumLength = 0;
SymbolReader.Decoders.EAN13.MaximumLength = 0;
SymbolReader.Decoders.EAN8.Enabled = true;
SymbolReader.Decoders.EAN8.MinimumLength = 0;
SymbolReader.Decoders.EAN8.MaximumLength = 0;
SymbolReader.Decoders.PDF417.Enabled = true;
SymbolReader.Decoders.PDF417.MinimumLength = 0;
SymbolReader.Decoders.PDF417.MaximumLength = 0;
SymbolReader.Decoders.UPCA.Enabled = true;
SymbolReader.Decoders.UPCA.MinimumLength = 0;
SymbolReader.Decoders.UPCA.MaximumLength = 0;
SymbolReader.Decoders.UPCE1.Enabled = true;
SymbolReader.Decoders.UPCE1.MinimumLength = 0;
SymbolReader.Decoders.UPCE1.MaximumLength =0;
SymbolReader.Decoders.UPCE0.Enabled = true;
SymbolReader.Decoders.UPCE0.MinimumLength = 0;
SymbolReader.Decoders.UPCE0.MaximumLength = 0;
*/
SymbolReader.Parameters.CodeIdType = Symbol.Barcode.CodeIdTypes.None;
SymbolReader.Parameters.ScanType = Symbol.Barcode.ScanTypes.Background;
SymbolReader.Parameters.LocalFeedback = Symbol.Barcode.DisabledEnabled.Enabled;
Scanner.SymbolReader.Parameters.Feedback.Success.BeepTime = 0;
}
}
}
}
Inside MainForm.cs
public void InitScanner(byte BatteryLevel)
{
// Create event handler delegate
if (Scanner.MyScann.Scanner.SymbolEventHandler == null)
{
Scanner.MyScann.Scanner.SymbolEventHandler = new EventHandler(this.SymbolReader_ReadNotify);
// Enable reader, with wait cursor
Scanner.MyScann.Scanner.SymbolReader.Actions.Enable();
Scanner.MyScann.Scanner.OpenAllBarcodes();
Scanner.MyScann.Scanner.ScannerEnabled = true;
}
// If we have both a reader and a reader data
if ((Scanner.MyScann.Scanner.SymbolReader != null) &&
(Scanner.MyScann.Scanner.SymbolReaderData != null))
{
// Submit a read
Scanner.MyScann.Scanner.SymbolReader.ReadNotify += Scanner.MyScann.Scanner.SymbolEventHandler;
Scanner.MyScann.Scanner.SymbolReader.Actions.Read(Scanner.MyScann.Scanner.SymbolReaderData);
}
}
public void SymbolReader_ReadNotify(object sender, EventArgs e)
{
Symbol.Barcode.ReaderData TheReaderData = Scanner.MyScann.Scanner.SymbolReader.GetNextReaderData();
if (TheReaderData.Result == Symbol.Results.SUCCESS /*&& (txtBarcode.Focused == true)*/)
{
// if (txtBarcode.Focused == true)
// {
// txtBarcode.Text = TheReaderData.Text.ToString();
MessageBox.Show(TheReaderData.Text.ToString());
SymbolReader_CycleScannerReader();
return;
// }
}
SymbolReader_CycleScannerReader();
}
public void SymbolReader_CycleScannerReader()
{
Scanner.MyScann.Scanner.SymbolReader.Actions.Read(Scanner.MyScann.Scanner.SymbolReaderData);
}
public void StartScanner()
{
bool flag = false;
try
{
Scanner.MyScann.Scanner.SymbolEventHandler = null;
Scanner.MyScann.Scanner.DeinitSymbolReader();
Scanner.MyScann.Scanner.ScannerEnabled = false;
if (!Scanner.MyScann.Scanner.ScannerEnabled)
{
Scanner.MyScann.Scanner.SymbolEventHandler = null;
Scanner.MyScann.Scanner.InitSymbolReader();
InitScanner(100);
flag = true;
}
}
catch
{
Scanner.MyScann.Scanner.SymbolEventHandler = null;
Scanner.MyScann.Scanner.InitSymbolReader();
InitScanner(100);
flag = true;
}
finally
{
if (!flag)
{
MessageBox.Show("Scanner Error");
}
}
}
void public void CloseScanner()
{
Scanner.MyScann.Scanner.SymbolEventHandler = null;
Scanner.MyScann.Scanner.DeinitSymbolReader();
}
void MainFormLoad(object sender, EventArgs e)
{
StartScanner();
}
void MainFormClosing(object sender, System.ComponentModel.CancelEventArgs e)
{
CloseScanner();
}
void ButtonExitClick(object sender, EventArgs e)
{
Scanner.MyScann.Scanner.DeinitSymbolReader();
this.Close();
Application.Exit();
}
Any help would be appreciated!
I'm not familiar with the symbol library, but from what i can see the problem is the ReadNotify event being raised at some point after the "deinitialization" of the scanner.
What you should do in the MainForm.CloseScanner() void is to first remove ALL handles added in the MainForm.InitScanner() and then call Scanner.DeinitSymbolReader().
Edit:
You should remove the handle with the -= operator, not assigning null reference.
Hope this helps.
try not calling 'DeinitSymbolReader' on exit, and see if that fixes it
Pete
My impression is that your application doesn't exit correctly with or without 'deinitSymbolReader'. It is possible that by calling deinitSymbolReader on a resource that has already been closed you are causing an access violation.
Maybe you should try giving up deinintSymbolReader, and try to also Dispose the scanner/trigger in the Form's Disposing Event.
What seems to be the problem is that you are Disposing of complex data structures, and right that you're changing them to null which basically means you're changing the reference and probably ensuring the GC will never get to free all the un-managed resources.
One indication that you are dealing with the improper manipulation of an un-managed resource is the fact that the second deinintSymbolReader shouldn't do anything (since all your resources are null) much less cause an error.
I have an application that uses triggers and scanner and it only needs an "enableScanner = false" and an "Scanner.Dispose()" if the scanner is not null.
Basically I need to communicate with a COM serial printer. There are 2 timers, one will print one ticket at time, and the others will hang up checking for errors and resuming the printing when the errors are gone.
For example: Printer is printing but if I press the pause button an error (read in the buffer) will get some booleans to 1 and after I read them I am able to tell what the error is and stop the printing.
My problem is in the method ErrorTimer_Elapsed() which is the timer elapsed event and probably is linked to the ErrorCheck and SendToCom (which is the printing method). The problem is that program detects errors well, but when in ErrorTimer_Elapsed() I try to repeatdly check for error status changes, I get IO errors like:
-Can't acces COM PORT
-The resource you required is in use
and so on.
Can you help me? Thanks, here's the code (about 180 lines), I'm bumping my head on this since 3 days :( :
using System;
using System.Collections;
using System.Configuration;
using System.IO;
using System.IO.Ports;
using System.Windows.Forms;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
#region Variabili di istanza
private ArrayList _filesToPrint = new ArrayList();
private static SerialPort _serialPort1 = new SerialPort();
private string _portName = ConfigurationSettings.AppSettings["COM"];
private string FilesPath = ConfigurationSettings.AppSettings["Path"];
private System.Timers.Timer PrintTimer = new System.Timers.Timer(2000);
private System.Timers.Timer ErrorTimer = new System.Timers.Timer(3500);
private bool PrintTimerIsActive = true;
private string HsCOMerrorStrings, PrintErrors;
#endregion
public Form1()
{
_serialPort1.PortName = _portName;
_serialPort1.ReadTimeout = 1000;
_IfFileExistsPrint();
}
private void _IfFileExistsPrint()
{
foreach (string file in Directory.GetFiles(FilesPath))
_filesToPrint.Add(file);
FileSystemWatcher SysWatch = new FileSystemWatcher(FilesPath, "*.*");
SysWatch.Created += new FileSystemEventHandler(SysWatch_Created);
SysWatch.EnableRaisingEvents = true;
PrintTimer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
PrintTimer.Start();
ErrorTimer.Elapsed += new System.Timers.ElapsedEventHandler(ErrorTimer_Elapsed);
}
private void SysWatch_Created(object Sender, FileSystemEventArgs w)
{
_filesToPrint.Add(w.FullPath);
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (_filesToPrint.Count > 0 && PrintTimerIsActive)
{
PrintTimer.Stop();
SendFilesToCom(_filesToPrint[0].ToString());
MessageBox.Show("Printing file :" + _filesToPrint[0].ToString());
File.Delete(_filesToPrint[0].ToString());
_filesToPrint.RemoveAt(0);
_filesToPrint.TrimToSize();
Console.Write(HsCOMerrorStrings);
PrintTimer.Start();
PrintErrors = ErrorCheck(HsCOMerrorStrings);
}
}
private void ErrorTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs d)
{
if (!_serialPort1.IsOpen)
{
try
{
_serialPort1.Open();
}
catch (Exception ex)
{
Console.WriteLine(ex.Data);
}
}
try
{
HsCOMerrorStrings = _serialPort1.ReadExisting();
_serialPort1.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Data);
}
Console.WriteLine(ErrorCheck(HsCOMerrorStrings));
}
private string ErrorCheck(string COMHostStatusReturn)
{
string ErrorsReturn = System.String.Empty;
string[] COMCode = COMHostStatusReturn.Split(',');
if (COMCode[1] == "1") { ErrorsReturn += "Carta Esaurita" + Environment.NewLine; }
if (COMCode[2] == "1") { ErrorsReturn += "Stampante in Pausa" + Environment.NewLine; }
if (COMCode[5] == "1") { ErrorsReturn += "Memoria Stampante Esaurita" + Environment.NewLine; }
if (COMCode[9] == "1") { ErrorsReturn += "Memoria RAM corrotta" + Environment.NewLine; }
if (COMCode[10] == "1") { ErrorsReturn += "Temperatura troppo bassa" + Environment.NewLine; }
if (COMCode[11] == "1") { ErrorsReturn += "Temperatura troppo alta" + Environment.NewLine; }
if (COMCode[7] == "1") { ErrorsReturn += "Partial Format Flag" + Environment.NewLine; }
if (ErrorsReturn != System.String.Empty)
{
if (PrintTimerIsActive == true)
{
PrintTimer.Stop();
if (!ErrorTimer.Enabled)
ErrorTimer.Start();
MessageBox.Show(ErrorsReturn);
}
PrintTimerIsActive = false;
}
else
{
if (PrintTimerIsActive == false)
{
ErrorTimer.Stop();
PrintTimer.Start();
PrintTimerIsActive = true;
}
}
return ErrorsReturn;
}
private void SendFilesToCom(string filePath)
{
if (!_serialPort1.IsOpen)
{
try
{
_serialPort1.Open();
}
catch (Exception ex)
{
}
}
try
{
using (System.IO.TextReader reader = File.OpenText(filePath))
{
string line;
while ((line = reader.ReadLine()) != null)
{
_serialPort1.WriteLine(line);
}
HsCOMerrorStrings = _serialPort1.ReadLine();
reader.Close();
_serialPort1.Close();
}
}
catch (Exception ex)
{
}
}
}
}
I have two methods that work together and they make a big double array (every 1/1000000S 5000 item) and this array should show a chart (Dundas chart).
But the chart is not updating.
Please help me!
Sorry for my bad English!
This my code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using Dundas.Charting.WinControl;
using Dundas.Charting.WinControl.Utilities;
namespace Online_Detector
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}
#region Fields
double fName = 0;
public object dataDigitalGlobal;
long num;
#endregion
#region Method
private void ManualSavetoFile(double Value, double Time)
{
//Get Path
//fName += 1;
string IntLocation = Convert.ToString(fName) + ".txt";
#region Write File
FileStream FOut = null;
try
{
if (File.Exists(IntLocation))
FOut = new FileStream(IntLocation, FileMode.Append, FileAccess.Write, FileShare.ReadWrite, 4096, true);
else
FOut = new FileStream(IntLocation, FileMode.Create, FileAccess.Write, FileShare.ReadWrite, 4096, true);
StreamWriter SOut = new StreamWriter(FOut);
// <Add Line To Export File >
lock (this)
{
if (FOut.CanWrite)
{
SOut.WriteLine(Value);
SOut.WriteLine(Time);
}
}
// <Add Line To Export File >
SOut.Close();
FOut.Close();
}
catch (IOException Err)
{
MessageBoxManager.OK = "&تاييد";
MessageBoxManager.Register();
MessageBox.Show("خطاي زير در عمليات تهيه فايل خروجي رخ داد:" + "\r" + Err.Message, "خطا", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.RtlReading);
MessageBoxManager.Unregister();
}
catch (FieldAccessException Err)
{
MessageBoxManager.OK = "&تاييد";
MessageBoxManager.Register();
MessageBox.Show("خطاي زير در عمليات تهيه فايل خروجي رخ داد:" + "\r" + Err.Message, "خطا", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.RtlReading);
MessageBoxManager.Unregister();
}
catch (Exception Err)
{
MessageBoxManager.OK = "&تاييد";
MessageBoxManager.Register();
MessageBox.Show("خطاي زير در عمليات تهيه فايل خروجي رخ داد:" + "\r" + Err.Message, "خطا", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.RtlReading);
MessageBoxManager.Unregister();
}
finally
{
FOut.Close();
}
#endregion //Write File
}
#endregion
#region Event on Tab Report
private void btnStart_Click(object sender, EventArgs e)
{
try
{
//check all the setting
axAdvAICtrl.ChannelScanStart = Convert.ToInt32(txtChannelStart.Text);
axAdvAICtrl.ChannelScanCount = Convert.ToInt32(txtChannelCount.Text);
int count = int.Parse(txtDataCount.Text);
// Ocx allocate the buffer of DataDigital ,equal to new object!
dataDigitalGlobal = null;
// Engage the FAI with Asychronous mode
count = axAdvAICtrl.AcquireBulkDataToMemory(count, out dataDigitalGlobal, -1, chkCylic.Checked, false);
num = 0;
// Disable all controls on the form
btnStart.Enabled = false;
// and only Enable the Stop button
btnEnd.Enabled = true;
}
catch (Exception err)
{
MessageBox.Show(err.Message, "Error");
axAdvAICtrl.StopAcquireBulkData(0);
}
}
private void btnEnd_Click(object sender, EventArgs e)
{
//stop the acquisition
axAdvAICtrl.StopAcquireBulkData(0);
// Enable all controls on the form
btnStart.Enabled = true;
// and only Disable the Stop button
btnEnd.Enabled = false;
}
#endregion
//this event every 1/500000
private void axAdvAICtrl_OnFirstHalfBulkDataReady(object sender, AxAdvAILib._IAdvAIEvents_OnFirstHalfBulkDataReadyEvent e)
{
#region "Get Data "
try
{
object analogArray = e.analogArray;
long i;
if (analogArray != null)
{
float[] voltage;
voltage = (float[])analogArray;
for (i = 0; i < Convert.ToInt32(txtDataCount.Text) / 2; i++)
{
// Write Data To Manual file
ManualSavetoFile(voltage[i], (num / axAdvAICtrl.DataSampleRate));
// Define some variables
int numberOfPointsInChart = Convert.ToInt32(txtDataCount.Text);
int numberOfPointsAfterRemoval = 1;
chaIon.Series["Series1"].Points.AddXY(xValue[arrayCounter], yValue[arrayCounter]);
// Keep a constant number of points by removing them from the left
while (chaIon.Series[0].Points.Count > numberOfPointsInChart)
{
// Remove data points on the left side
while (chaIon.Series[0].Points.Count > numberOfPointsAfterRemoval)
{
chaIon.Series[0].Points.RemoveAt(0);
}
}
chaIon.Invalidate();
num++;
}
}
}
catch (Exception err)
{
threadChart.Abort();
MessageBox.Show(err.Message, "Error");
}
#endregion
}
//this event every 1/500000
private void axAdvAICtrl_OnSecondHalfBulkDataReady(object sender, AxAdvAILib._IAdvAIEvents_OnSecondHalfBulkDataReadyEvent e)
{
#region "Get Data "
try
{
object analogArray = e.analogArray;
long i;
if (analogArray != null)
{
float[] voltage;
voltage = (float[])analogArray;
for (i = 0; i < Convert.ToInt32(txtDataCount.Text) / 2; i++)
{
// Write Data To Manual file
ManualSavetoFile(voltage[i], (num / axAdvAICtrl.DataSampleRate));
// Define some variables
int numberOfPointsInChart = Convert.ToInt32(txtDataCount.Text);
int numberOfPointsAfterRemoval = 1;
chaIon.Series["Series1"].Points.AddXY(xValue[arrayCounter], yValue[arrayCounter]);
// Keep a constant number of points by removing them from the left
while (chaIon.Series[0].Points.Count > numberOfPointsInChart)
{
// Remove data points on the left side
while (chaIon.Series[0].Points.Count > numberOfPointsAfterRemoval)
{
chaIon.Series[0].Points.RemoveAt(0);
}
}
chaIon.Invalidate();
num++;
}
}
}
catch (Exception err)
{
threadChart.Abort();
MessageBox.Show(err.Message, "Error");
}
#endregion
}
private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
axAdvAICtrl.StopAcquireBulkData(0);
}
}
}
Typically, any updates to UI components should be done on the UI thread, via Control.Invoke (or the WPF equivalent). It is possible that your changes are causing exceptions that are being swallowed somewhere.
Does your code work frmo the UI thread? You can still use a BackgroundWorker - you just need to do the updates (ideally in batches) via Invoke.