【问题标题】:C# StreamReader ReadLine() hangs on second attempt, unless threads exitC# StreamReader ReadLine() 在第二次尝试时挂起,除非线程退出
【发布时间】:2019-02-24 06:52:19
【问题描述】:

我从另一个开发人员那里继承了下面的代码,它向外部系统发出请求。

我使用不同的“方法”参数值(来自 BackgroundWorker)调用 GenerateRequest 方法,所有这些都可以正常工作。然后当我进行第二次调用时,它仍然适用于除一个“方法”值之外的所有值(它还包含“参数”值的不同值,我将在下面也包括调用),它挂在 StreamReader ReadLine( ) 称呼。但是,如果我在允许 10-20 秒的时间内调试并逐步执行代码,输出会显示一些“线程 0xd0f0 已退出,代码为 0 (0x0)”的消息,然后代码就可以工作了。

我觉得我正在执行这项工作的线程有问题,但我无法弄清楚,请帮助。

这每次都有效;

   ClientParameters parameters = new ClientParameters();
   string request = requestHandler.GenerateRequest("GetFunctions", parameters);

这仅在第一次有效,除非我调试并逐步执行,让线程有时间退出。

ClientParameters parameters = new ClientParameters();
        parameters.Filter = new ClientParametersFilter();
        parameters.Filter.Demographics = "";
        parameters.Filter.Medication = "";
        parameters.Filter.MinEffectiveDate = DateTime.Now;
        parameters.Filter.MaxEffectiveDate = DateTime.MaxValue;
        string request = null;
        try
        {
            request = requestHandler.GenerateRequest("GetRecord", parameters);
        }
        catch(Exception e)
        {
            // log error
            return null;
        }

Hear 是发出请求的类;

public class MyRequestHandler : IRequestHandler{
public string GenerateRequest(string method, ClientParameters parameters)
{
    ClientIntegrationRequest request = new ClientIntegrationRequest();
    request.APIKey = ApplicationSettings.APIKey;
    request.Function = method;
    request.FunctionVersion = 1.0M;
    request.RequestUID = DateTime.Now.ToString();
    request.DeviceID = ApplicationSettings.DeviceId;
    request.DeviceVersion = ApplicationSettings.DeviceVersion;
    request.FunctionParameters = parameters;

    XmlSerializer ser = new XmlSerializer(typeof(ClientIntegrationRequest));
    string xml;
    using (MemoryStream m = new MemoryStream())
    {
        ser.Serialize(m, request);
        // reset to 0
        m.Position = 0;
        xml = new StreamReader(m).ReadToEnd();
    }

    try
    {
        TcpClient tcpClient = new TcpClient("127.0.0.1", ApplicationSettings.Port);
        NetworkStream netStream = tcpClient.GetStream();
        if (netStream.CanWrite)
        {
            xml = xml + "\n";
            Byte[] sendBytes = Encoding.UTF8.GetBytes(xml);
            netStream.Write(sendBytes, 0, sendBytes.Length);
            netStream.Flush();
        }
        else
        {
            tcpClient.Close();
            netStream.Close();
            return null;
        }
        netStream = tcpClient.GetStream();
        if (netStream.CanRead)
        {
            StreamReader l_textReader = new StreamReader(netStream);
            string str = l_textReader.ReadLine(); // Here's the issue
            l_textReader.Close();           
            tcpClient.Close();
            netStream.Close();
            return str.ToString();
        }
        else
        {
            tcpClient.Close();
            netStream.Close();
            return null;
        }
    }
    catch (SocketException e)
    {
        // log error
        return null;
    }
    catch (Exception e)
    {
        // log error
        return null;
    }
}}

【问题讨论】:

    标签: c# backgroundworker tcpclient streamreader


    【解决方案1】:

    如果您查看 Microsoft 示例:https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.tcpclient.getstream?view=netframework-4.7.2 可以看到代码通过读取字节数组返回的内容的低级代码读取客户端流:

    if (netStream.CanRead)
    {
        // Reads NetworkStream into a byte buffer.
        byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
    
        // Read can return anything from 0 to numBytesToRead. 
        // This method blocks until at least one byte is read.
        netStream.Read (bytes, 0, (int)tcpClient.ReceiveBufferSize);
    
        // Returns the data received from the host to the console.
        string returndata = Encoding.UTF8.GetString (bytes);
    
        Console.WriteLine ("This is what the host returned to you: " + returndata);
    
    }
    

    你可以试试这个阅读方法吗?

    【讨论】:

    • 您好,感谢您的建议。不幸的是,我已经尝试过这种方法。我刚刚再次尝试以确保得到相同的结果,现在代码在第二次调用时挂在 NetworkStream Read() 方法上。
    • 在文章中:“调用Read方法接收来自远程主机的数据。这两种方法都会阻塞,直到执行指定的操作。您可以通过检查DataAvailable来避免阻塞读取操作属性。真值表示数据已经从远程主机到达并且可以读取。在这种情况下,读取保证立即完成。如果远程主机关闭其连接,读取将立即返回零字节。"。您可以在读取之前尝试测试 DataAvailable 属性吗?
    • 当我在 Read() 之前调用 netStream.DataAvailable 时,它​​每次都等于 false,即使在没有挂在 Read() 上的调用上也是如此。没用:(
    猜你喜欢
    • 1970-01-01
    • 2016-10-17
    • 2014-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多