C# - 使用多输入设备的多线程

时间:2015-11-03 19:27:03

标签: c# multithreading input printing

我目前正在编写一个C#应用程序,它将接受来自多个USB连接输入设备的输入。使用the Raw Input library,我能够识别输入设备,然后根据输入设备完成操作。

示例:设备A输入是作为一系列击键接收的,构建了一个字符串,使用'内置的'来查询数据库。字符串作为参数,打印机A打印结果。

我遇到的问题是多个设备同时输入值时的延迟。设备A输入与设备B同时接收;打印机A立即打印,但打印机B在打印时遇到一些延迟。延迟时间不超过一秒,但对于此项目的预期目的而言,这是一秒钟。我正在使用条形码扫描仪所以我会说由于缺乏更好的定量测量,整个字符串的输入是闪电

我不认为我的问题需要代表我的任何代码,但如果需要帮助回答问题,请告诉我,我可以提供一个代码段。我只是在寻找一个示例或策略来使用多线程输入到输出,如果这是有道理的。

感谢任何帮助。

编辑(添加当前代码):

private readonly RawInput _rawinput;
const bool CaptureOnlyInForeground = true;

public InputForm()
{
    InitializeComponent();

    _rawinput = new RawInput(Handle, CaptureOnlyInForeground);
}

string Scanner1ID;
string Scanner2ID;
string Printer1IP;
string Printer2IP;

int NumberIdentifier;
string ScannedItem;
string ScannedKey;

PLabel NewLabel = New PLabel();

//Various methods are used to identify each scanner and printer, print commands are sent via the TcpClient class in conjunction with a StreamWriter.

void StartScanning(object sender, EventArgs e)
{
    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

    _rawinput.AddMessageFilter();
    Win32.DeviceAudit();
    _rawinput.KeyPressed += OnItemScanned;
}

private void OnItemScanned(object sender, RawInputEventArg e)
{
    ScannedKey = e.KeyPressEvent.VKeyName.Replace("D", "");
    if (int.TryParse(ScannedKey, out NumberIdentifier)
    {
        ScannedItem += ScannedKey;

        if (e.KeyPressEvent.VKey == 13 || ScannedItem.Length == 10)
        {
            InOutList.Items.Add(ScannedItem); //Adds to list in form
            if (e.KeyPressEvent.DeviceHandle.ToString() == Scanner1ID)
            {
                NewLabel.querySQL(ScannedItem);
                Printer1Writer.Write(NewLabel.Results);
                Printer1Writer.Flush();
             }
             else if (e.KeyPressEvent.DeviceHandle.ToString() == Scanner2ID)
            {
                NewLabel.pingSQL(ScannedHWB);
                if (Client2Printer2.Connected)
                {
                    NewLabel.querySQL(ScannedItem);
                    Printer2Writer.Write(NewLabel.Results);
                    Printer2Writer.Flush();
                }    
            }

            ScannedItem = "";
        }
    }
}

我可能已经遗漏了一些东西,但希望这已经足够了。

1 个答案:

答案 0 :(得分:2)

根据你链接的文章

  

每个窗口的句柄与上一节中描述的已注册设备相关联,因此必须检查它收到的消息,并在检测到WM_INPUT时执行适当的操作。

Windows消息处理是一种协作式多任务处理。在当前的消息从处理返回之前,无法从消息队列中处理新消息。

如果您的代码通过在数据库中执行任何操作来响应WM_INPUT,则 没有其他事件可以处理,直到完成为止。

您可以使用生产者/消费者模式解决此问题。让处理WM_INPUT的代码将处理所需的信息放入诸如BlockingCollection之类的结构中,并从BlockingCollection中读取一个单独的线程并完成工作。

根据您的需要,每个原始输入设备可能只有一个BlockingCollection,或者只有一个。如果是后者,放入BlockingCollection的部分信息可能是生成输入的原始设备的标识符。