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

C#-使用多个输入设备的多线程处理,c#,multithreading,input,printing,C#,Multithreading,Input,Printing,我目前正在编写一个C#应用程序,它将接受来自多个USB连接输入设备的输入。使用,我能够识别输入设备,然后根据输入设备完成操作 示例:设备A通过一系列按键接收输入,生成字符串,使用“生成”字符串作为参数查询数据库,打印机A打印结果 我遇到的问题是多个设备同时输入值时的延迟。与设备B同时接收设备A输入;打印机A立即打印,但打印机B在打印过程中遇到了一些延迟。延迟时间不超过一秒钟,但对于该项目的预期目的来说,这一秒太长了。我正在使用条形码扫描仪,所以我会说,由于缺乏更好的定量测量,整个字符串的输入速度

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

示例:设备A通过一系列按键接收输入,生成字符串,使用“生成”字符串作为参数查询数据库,打印机A打印结果

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

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

感谢您的帮助

编辑(添加当前代码):


我可能遗漏了什么,但希望这足够了。

根据您链接的文章

因此,如前一节所述,其句柄与注册设备关联的每个窗口必须检查其接收的消息,并在检测到WM_输入时采取适当的措施

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

如果您的代码通过在数据库中执行任何需要的操作来响应WM_输入,那么在完成之前,其他事件都无法处理

您可以通过使用生产者/消费者模式来解决这个问题。让处理WM_输入的代码将处理所需的信息放入一个结构(如a),并从BlockingCollection中读取一个单独的线程,然后执行该工作


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

几个问题。。。设备A总是转到打印机A,还是可以转到打印机B?原始输入库是否支持多线程?因为可以想象,您可以将每个设备设置在自己的线程上。如果第一个问题的答案是否定的,你可以想象使用线程来阅读,然后使用某种
ConcurrentQueue
发送到打印机。不可能用简单的答案来回答-你要么在寻找教程(这是离题的),要么需要很多关于如何设置的细节(遵循详细要求)或您需要处理当前代码的问题(未包含此代码,因此无法提出更改建议)。这可能有助于了解您当前如何处理输入设备。我设想您需要一个主控制线程,每个设备都需要一个线程:1.ScannerA,2.ScannerB,3.PrinterA,4.PrinterB每个扫描设备线程都会回调传递值的主控制线程。主控制线程会传递该值关闭相关打印机线程的值。或者每个扫描仪线程都有一个对相关打印机线程的引用,它可以直接调用该线程,而不是通过主控制线程进行路由。@Moo Juice设备a将始终打印到打印机a,依此类推。原始输入支持多线程,是否提供我当前的代码帮助?@DelKirksey、 非常:)瞧。这就是我想可能会发生的事。是的。您的OnItemScanned事件处理程序需要快速返回。制作人/消费者是一条出路。这听起来很有希望,但我对BlockingCollection不太熟悉,我会调查一下。谢谢。@DelKirksey:在我链接的MSDN文档中,在页面底部有一个很好的例子。经过一个小时的阅读和调查,我想我可以理解使用BlockingCollection对我当前的流程有何好处。我唯一的问题(目前)是如何使用BlockingCollection处理多个独立(非常快)的击键?或者我应该处理击键,然后仅利用BlockingCollection进行处理@埃里克。
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 = "";
        }
    }
}