使用tcp客户端和streamreader阻塞while循环

时间:2017-03-21 16:20:58

标签: c#

这种方法冻结了我的GUI,我不明白为什么。

特别是它被卡在while ((feedback = reader.ReadLine()) != null)

我试过通过检查reader.EndOfStream()并尝试相同的结果来打破循环。打印机按预期运行并打印标签,并且还返回预期的反馈。它只是坐在循环中,在控制台中闪烁光标。

我可以摆脱循环,因为我真的不需要这个程序的反馈,但我仍然想了解发生了什么。

它被称为这样:

private void printBarcodeButton_Click(object sender, RoutedEventArgs e)
    {
        ...
        code to get id and name
        ...

        messageTextBlock.Text = "Printing Barcode.";

        using (var printer = new BarcodePrinter())
        {
            printer.printBarcode(employeeID, employeeName);
        }

        messageTextBlock.Text = "Barcode printed.";
    }

以下是方法:

public void printBarcode(string employeeID, string employeeName)
    {
        var projectFolder = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;
        var printerScript = Path.Combine(projectFolder, @"PrinterScript.txt");

        // Printer IP Address and communication port
        string ipAddress = "10.1.10.23";
        int port = 9100;

        // Fingerprint Commands read from text and sent to printer
        using (TcpClient client = new TcpClient())
        {
            client.Connect(ipAddress, port);
            using (var stream = client.GetStream())
            {
                // open the script file
                using (var file = new StreamReader(printerScript))
                {
                    // open a stream to get feedback from printer
                    string feedback = "none yet";
                    using (var reader = new StreamReader(stream))
                    {
                        // open stream to send commands to printer
                        using (var writer = new StreamWriter(stream))
                        {
                            string command, script = null;
                            while ((command = file.ReadLine()) != null)
                            {
                                // send all non-empty lines in script 
                                if (command != string.Empty && !command.Contains("**"))
                                {
                                    command = command.Replace("_employeeID_", employeeID);
                                    command = command.Replace("_employeeName_", employeeName);
                                    script += command + "\n";
                                }
                            }
                            writer.Write(script);
                            writer.Flush();

                            // display data sent back from printer (including echo of commands)
                            while ((feedback = reader.ReadLine()) != null)
                            {
                                Console.WriteLine(feedback);                                    
                            }
                        }
                    }
                }
            }
        }
    }

3 个答案:

答案 0 :(得分:1)

摘自MSDN

  

一条线被定义为一个字符序列,后跟一个换行符(" \ n"),一个回车符(" \ r"),或者紧接着一个回车符通过换行符(" \ r \ n")。返回的字符串不包含终止回车符或换行符。如果到达输入流的末尾,则返回值为null。

您可能尚未达到\n\r\r\n,也未达到输入的结尾。这里需要注意的是通常"输入结束"意味着另一个点(您的场景中的打印机)关闭了频道,而且很可能它没有这样做。

我建议在接收时使用超时,因为这些设备通常会立即发送所有数据。如果这个选项无效,还有其他选项,请问,但它应该在大多数情况下都有效。

答案 1 :(得分:0)

只需添加:

while ((feedback = reader.ReadLine()) != null)
                        {
                            Console.WriteLine(feedback);
                            if (feedback == "Ok") break;
                        }

它甚至在发生错误后发送Ok消息,因此涵盖了所有内容。

答案 2 :(得分:-1)

我没有在while条件中对命令进行赋值,而是尝试将它作为while语句中的最后一个命令:

string command, script = null;
command = file.ReadLine();
while (command != null)
{
// send all non-empty lines in script 
     if (command != string.Empty && !command.Contains("**"))
     {
     command = command.Replace("_employeeID_", employeeID);
     command = command.Replace("_employeeName_", employeeName);
     script += command + "\n";
     }
     command = file.ReadLine();
}

这种改变只会在检查while循环条件之前确保显式读取,并确保while循环中的赋值不是条件。