简体   繁体   English

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

[英]Stuck in while loop using tcp client and streamreader

This method is freezing my GUI and I don't understand why. 这种方法冻结了我的GUI,我不明白为什么。

Specifically it's getting stuck in while ((feedback = reader.ReadLine()) != null) 特别是它被卡住了while ((feedback = reader.ReadLine()) != null)

I've tried breaking out of the loop by checking reader.EndOfStream() with the same result. 我试过通过检查reader.EndOfStream()得到相同的结果来打破循环。 The printer is behaving as expected and printing the label, and the expected feedback is also being returned. 打印机按预期运行并打印标签,并且还返回预期的反馈。 It just sits in the loop, blinking a cursor in the console. 它只是坐在循环中,在控制台中闪烁光标。

I can get rid of the loop, as I don't really need the feedback for this program, but I would still like to understand what's happening. 我可以摆脱循环,因为我真的不需要这个程序的反馈,但我仍然想了解发生了什么。

It's being called like this: 它被称为这样:

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

Here is the method: 这是方法:

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

Excerpt from MSDN : 摘自MSDN

A line is defined as a sequence of characters followed by a line feed ("\\n"), a carriage return ("\\r"), or a carriage return immediately followed by a line feed ("\\r\\n"). 一行被定义为一个字符序列,后跟一个换行符(“\\ n”),一个回车符(“\\ r”),或一个回车符后面紧跟一个换行符(“\\ r \\ n”)。 The string that is returned does not contain the terminating carriage return or line feed. 返回的字符串不包含终止回车符或换行符。 The returned value is null if the end of the input stream is reached. 如果到达输入流的末尾,则返回的值为null。

You probably haven't reached a \\n , \\r or \\r\\n nor the end of the input. 您可能还没有到达\\n\\r\\r\\n也没有到达输入的末尾。 The caveat here is that normally "end of the input" means that the other point (the printer in your scenario) closes the channel and most probably it is not doing that. 这里需要注意的是,通常“输入结束”意味着另一个点(您的场景中的打印机)关闭了通道,并且很可能它没有这样做。

I recommend using timeouts on the reception as those devices normally send all the data at once. 我建议在接收时使用超时,因为这些设备通常会立即发送所有数据。 There are other options if this one is not valid, just ask, but it should work most of the times. 如果这个选项无效,还有其他选项,请问,但它应该在大多数情况下都有效。

Simply has to add this: 只需要添加这个:

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

It even sends the Ok message after an error, so that covers everything. 它甚至在发生错误后发送Ok消息,因此涵盖了所有内容。

Instead of having the assignment to the command within the while condition, I would try putting it as the last command in the while statement instead: 我没有在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();
}

This change would merely ensure explicit reading before checking the while-loop condition, and assures that the assignment within the while-loop is not the condition. 这种改变只会在检查while循环条件之前确保显式读取,并确保while循环内的赋值不是条件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM