Question

So I wrote a quick example program to better understand the Janam scanner gun however I am running into problems that I have never seen though I believe may be caused due to being on different threads and passing values between them. So I do not believe I am correctly using delegates. and help would be appreciated.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Scanner;

namespace ScannerTest
{
public partial class Form1 : Form
{
    //Delegates
    private delegate void RefreshValuesDelegate();
    private delegate void AddScannedItemDelegate(Item item);
    // SINGLETON //////////////////////////////////////
    private static Form1 instance = null;

    public static Form1 GetInstance()
    {
        if (instance == null)
            instance = new Form1();

        return instance;
    }
    ///////////////////////////////////////////////////

    public Form1()
    {
        InitializeComponent();
    }
    void Form1_Load(object sender, EventArgs e)
    {
        /**************/
        //SCANNER ACTIVATE                       

        GlobalScanner.GetInstance().Close();
        GlobalScanner.GetInstance().BarcodeDelegateDirector = new GlobalScanner.BarcodeDelegate(Form1.GetInstance().processScannedBarcode);
        GlobalScanner.GetInstance().Open();
        /**************/

    }
    // Add the new part unless the part number contains 
    // spaces. In that case cancel the add. 
    private void button1_Click(object sender, EventArgs e)
    {
        if (textBox1.Text.Equals("") || textBox2.Text.Equals(""))
        {
            MessageBox.Show("item names or barcodes cannot be blank.");
        }
        else
        {
            Item temp = new Item(textBox1.Text, textBox2.Text, DateTime.Now);
            if (temp.ItemCheck == true)
            {
                AddToList(temp);
            }
        }
    }
    public void processScannedBarcode(string scannedBarcode)
    {
        if (scannedBarcode != null && scannedBarcode.Length > 0) // 0 = SUCCESS Symbol.Results.SUCCESS
        {
            Item temp = new Item();
            temp.ItemName = "N/A";
            temp.BarcodeNumber = scannedBarcode;
            String tempDate = DateTime.Now.ToShortDateString();
            String tempTime = DateTime.Now.ToShortTimeString();
            temp.ScanDate = tempDate + tempTime;
            AddScannedItem(temp);
        }
    }
    private void AddScannedItem(Item item)
    {
        if (this.InvokeRequired == true)
        {
            this.Invoke(new AddScannedItemDelegate(AddScannedItem), new object[] { item });
        }
        else
        {
            this.textBox2.Text = item.BarcodeNumber;
            this.textBox1.Text = item.ItemName; // description not available
            item.ScanDate = DateTime.Now.ToLongDateString();
            //DateTime readDate = DateTime.Now;
            //cargo.SetReadDate(readDate);
            RefreshValues();
            AddToList(item);
        }
    }
    private void AddToList(Item item)
    {
        string tempItem = item.ItemName;
        string tempBarcode = item.BarcodeNumber;
        string tempDate = item.ScanDate;
        ListViewItem newRow = new ListViewItem(tempItem);
        newRow.SubItems.Add(tempBarcode);
        newRow.SubItems.Add(tempDate);
        listView1.Items.Add(newRow);
        RefreshValues();
        //MessageBox.Show(string.Format("TextBox1: {0} TextBox2: {1}", tempItem, tempBarcode));
        textBox2.Text = "";
        textBox1.Text = "";
    }
    public void RefreshValues()
    {
        if (this.InvokeRequired == true)
        {
            this.Invoke(new RefreshValuesDelegate(RefreshValues));
        }
        else
        {
            listView1.Refresh();
        }
    }
}

// A simple business object for example purposes. 
public class Item
{
    private string name;
    private string number;
    private string date;
    private bool check = true;

    public Item() { }
    public Item(string nameForItem, string numberForBarcode, DateTime scandate)
    {
        ItemName = nameForItem;
        BarcodeNumber = numberForBarcode;
        date = scandate.ToShortDateString();
    }

    public string ItemName
    {
        get 
        { 
            return name; 
        }
        set 
        {
            if (value.Length <= 45)
            {
                name = value;
            }
            else
            {
                MessageBox.Show("Item name to long. Must be less than 45 characters.");
                ItemCheck = false;
            }
        }
    }

    public string BarcodeNumber
    {
        get 
        { 
            return number; 
        }
        set 
        {
            if (value.Length <= 20)
            {
                number = value; 
            }
            else
            {
                MessageBox.Show("Barcode is to long. Must be less than 20 digits.");
                ItemCheck = false;
            }
        }
    }
    public string ScanDate
    {
        get
        {
            return date;
        }
        set
        {
            date = value;
        }
    }

    public bool ItemCheck
    {
        get
        {
            return check;
        }
        set
        {
            check = value;
        }
    }
}
}

So manually typing out the values works properly but when the scanner is activated and reads in a value. The debugger shows the proper values getting set and stored as the code goes through the list however the screen shows nothing from the scanner and does not save the value to the listview as it does when manually typed.

Like I said before I believe its a problem with delegates and the scanner thread passing the value to the main thread that it just doesn't like.

Thanks for the help in advance.

Here is a view of manually typing in values manual typing

Here is a view of scanner being used. I un-commented the messagebox so you could see it is picking up something. scanner

Answer to someones question: enter image description here

Here is the global scanner for those that would like to check it out.

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace Scanner
{
public class GlobalScanner
{
    #region About using the delegate in this class
    /*  We are actually using one central class to do the scanning, but user can scan from different screens.
      * If we don't have a delegate we will have the following scenario. We scan the barcode, the barcode will be 
      * captured in our scanner implementation class "For example: IntermecBarcodeScanner" and we will have no way to return
      * the barcode back to the scanning screen. The delegate will actually help us to do that job. The delegate will
      * be associated with a method inside the scanning form. It will carry the scanned barcode over to that method
      * inside the scanning form.
      * 
      * We need 3 main things to get the delegate working:
      * 1- Declare a delegate variable
           public delegate void BarcodeDelegate(string barcode);
      * 2- Initialize a delegate and associate it with the appropropriate method in the scanning form: 
      *     Example: GlobalScanner.GetInstance().BarcodeDelegateDirector = new GlobalScanner.BarcodeDelegate(this.ScanBarcodeEvent);
      *     We need the above line of code to be in the scanning form. That's how we associate the ScanBarcodeEvent() method
      *     with the delegate that is in the GlobalScanner class.
      * 3- In GlobalScanner class we created two variables to help us to connect to the scanner implementation class such as
      *    the IntermecBarcodeScanner. Those two variables are: barcodeDelegateInstance and barcodeData
      */
    #endregion

    //Declare a delegate
    public delegate void BarcodeDelegate(string barcode);

    private IBarcodeScanner scanner = null;

    // SINGLETON //////////////////////////////////////
    private static GlobalScanner instance = null;

    public static GlobalScanner GetInstance()
    {
        if (instance == null)
        {
            instance = new GlobalScanner();
        }

        return instance;
    }
    // ////////////////////////////////////////////////


    private BarcodeDelegate barcodeDelegateInstance = null;
    //BarcodeDelegateDirector will be accessed to associate the method 
    //that's in the scanning form with the delegate
    public  BarcodeDelegate BarcodeDelegateDirector
    {
        get { return barcodeDelegateInstance; }
        set { barcodeDelegateInstance = value; }
    }

    //We also created this variable to set the barcode value from other classes such as IntermecBarcodeScanner
    private string barcodeData;
    public string BarcodeData
    {
        get { return barcodeData; }
        set
        {
            barcodeData = value;
            barcodeDelegateInstance(barcodeData); //barcodeData is the scanned barcode and it comes from the GlobalScanner implementation
        }
    }

    public void Open()
    {
        String deviceName = Platform.GetOEMInfo();
        if (deviceName != null)
        {                
            if (scanner == null)
            {
                if (deviceName.Equals(Global.INTERMEC_DEVICE_1) || deviceName.Equals(Global.INTERMEC_DEVICE_2) || deviceName.Equals(Global.INTERMEC_DEVICE_3))
                    scanner = new IntermecBarcodeScanner();
                else if (deviceName.Equals(Global.JANAM_DEVICE_1) || deviceName.Equals(Global.JANAM_DEVICE_2) || deviceName.Equals(Global.JANAM_DEVICE_3))
                    scanner = new JanamXMBarcodeScanner();
                else if (deviceName.Equals(Global.JANAM_XG_DEVICE_1) || deviceName.Equals(Global.JANAM_XG_DEVICE_2) || deviceName.Equals(Global.JANAM_XG_DEVICE_3))
                    scanner = new JanamXGBarcodeScanner();
                else if (deviceName.Equals(Global.MOTOROLA_DEVICE_1) || deviceName.Equals(Global.MOTOROLA_DEVICE_2) || deviceName.Equals(Global.MOTOROLA_DEVICE_3))
                    scanner = new MotorolaBarcodeScanner();

            }

            scanner.Open();
        }
    }

    public void Close()
    {
        if (scanner != null)
        {
            scanner.Close();
        }

    }
}
}
Was it helpful?

Solution 3

So I finally figured out how to resolve my problem although I do not fully understand why this fixes my problem and only stumbled upon it when I was setting all my textbox1.text to form1.GetInstance().textbox1.text which started making my manual input act the same way my scan inputs were. This lead me to believe that my form1.instance was having issues setting the items on my form. For future answer seekers to this same problem, I fixed my code with the following change. From this

/**************/
//SCANNER ACTIVATE                       
GlobalScanner.GetInstance().Close();
GlobalScanner.GetInstance().BarcodeDelegateDirector = new GlobalScanner.BarcodeDelegate(Form1.GetInstance().processScannedBarcode);
GlobalScanner.GetInstance().Open();
/**************/

To this

/**************/
//SCANNER ACTIVATE
GlobalScanner.GetInstance().Close();
GlobalScanner.GetInstance().BarcodeDelegateDirector = new GlobalScanner.BarcodeDelegate(processScannedBarcode);
GlobalScanner.GetInstance().Open();
/**************/

Simply removing the Form1.GetInstance() resolved this issue however there is only one instance so there should really not be a difference. If anyone can explain this for me and future answer seekers, we would appreciate it very much.

OTHER TIPS

If you think it is a inter-thread problem you might use a lock object to ensure only a single thread can access the event data:

a global object lockObject = new object(); has to be defined and in AddToList suround all code with lock (lockObject) { } the above ensures that only one AddToList is running at a time.

The other diff I see to my delegates with barcode scanners is the delegate usage: in my code I first declare a new var of the delegate and then call the invoke on the var. But that should not make a difference in function.

If your device's scanner is set to append a Carriage Return to the end of a scan, your TextBox may be blanking that line.

For example, what happens if you write, "Hello World!\n" to your Text Box?

UPDATE:

Look for setting to configure the device's Scan options (called Decoding in the pic below).

Settings

That is for my Datalogic Falcon, but your XM66 should look something like this:

XM66Settings

From there, you may need to tweak the Scanner settings.

ScannerSettings

Again, your XM66 will be different, like this:

XM66ScanWedge

The problem is that instance remains null on every call of GetInstance(). The GetInstance() creates a new form1 recursively (just used the debugger and stepped thru the following code before instance=this; was added:

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 FormInstance
{
    public partial class Form1 : Form
    {
        private static Form1 instance = null;

        public static Form1 GetInstance()
        {
            if (instance == null)
                instance = new Form1();

            return instance;
        }

        public Form1()
        {
            InitializeComponent();
            // doTest();   //results in a recursive call!
            ///without the following instance will never be different than null, as GetInstance creates new Form on every call!
            instance = this;    
        }
        void doTest()
        {
            Form f1 = this;
            Form f2 = Form1.GetInstance();
            System.Diagnostics.Debug.WriteLine("f1=" + f2.GetType().FullName);
            System.Diagnostics.Debug.WriteLine("f2=" + f2.GetType().FullName);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            doTest();   //does also not return the current form!
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top