2

因此,我编写了一个快速示例程序来更好地理解 Janam 扫描枪,但是我遇到了我从未见过的问题,尽管我认为可能是由于位于不同的线程上并在它们之间传递值造成的。所以我不相信我正确地使用了代表。和帮助将不胜感激。

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;
        }
    }
}
}

因此,手动输入值可以正常工作,但是当扫描仪被激活并读取一个值时。当代码通过列表时,调试器会显示设置和存储的正确值,但是屏幕不会显示来自扫描仪的任何内容,并且不会像手动键入时那样将值保存到列表视图中。

就像我之前所说的,我认为委托和扫描线程将值传递给它不喜欢的主线程是一个问题。

我在这里先向您的帮助表示感谢。

这是手动输入值的视图 手动打字

这是正在使用的扫描仪的视图。我取消了消息框的注释,所以你可以看到它正在接收一些东西。 扫描器

回答某人的问题: 在此处输入图像描述

这是想要检查的人的全局扫描仪。

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();
        }

    }
}
}
4

4 回答 4

1

如果您认为这是线程间问题,您可以使用锁定对象来确保只有单个线程可以访问事件数据:

一个全局对象 lockObject = new object(); 必须定义并在 AddToList 中使用 lock (lockObject) { } 包围所有代码,确保一次只有一个 AddToList 正在运行。

我使用条形码扫描仪向我的委托人看到的另一个差异是委托的用法:在我的代码中,我首先声明委托的新 var,然后在 var 上调用调用。但这不应该对功能产生影响。

于 2013-08-07T04:13:23.680 回答
1

如果您设备的扫描仪设置为在扫描结束时附加回车,则您的 TextBox 可能会将该行空白。

例如,如果您在文本框中写入“Hello World!\n”会发生什么?

更新:

查找设置以配置设备的扫描选项(在下图中称为解码)。

设置

这适用于我的 Datalogic Falcon,但您的 XM66 应该如下所示:

XM66设置

从那里,您可能需要调整扫描仪设置。

扫描仪设置

同样,您的 XM66 将有所不同,如下所示:

XM66ScanWedge

于 2013-08-06T17:21:11.387 回答
1

问题是实例在每次调用 GetInstance() 时都保持为空。GetInstance() 以递归方式创建一个新的 form1(在添加 instance=this; 之前,只需使用调试器并逐步执行以下代码:

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!
        }
    }
}
于 2013-08-08T08:22:02.867 回答
1

所以我终于想出了如何解决我的问题,尽管我不完全理解为什么这可以解决我的问题,并且只是在我将所有 textbox1.text 设置为 form1.GetInstance().textbox1.text 时才偶然发现它开始制作我的手册输入的行为与我的扫描输入相同。这让我相信我的 form1.instance 在我的表单上设置项目时遇到问题。对于同样问题的未来寻求答案的人,我通过以下更改修复了我的代码。由此

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

对此

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

只需删除 Form1.GetInstance() 即可解决此问题,但是只有一个实例,因此实际上应该没有区别。如果有人可以为我和未来的答案寻求者解释这一点,我们将非常感激。

于 2013-08-07T19:21:09.210 回答