为什么这个代码挂在从一个StreamReader达到第一的ReadLine? [英] Why does this code hang on reaching the first ReadLine from a StreamReader?
问题描述
我经过一个大文件中的第一个参数下SendXMLFile(),但是,因为它是导致手持设备挂起/冻结我暂时硬编码一个更小的文件(3 KB,而不是1121 KB)进行测试。
I was passing a large file in the first arg to SendXMLFile() below but, since it was causing the handheld device to "hang"/"freeze" I temporarily hard-coded a much smaller file (3 KB as opposed to 1121 KB) for testing.
该文件确实存在(在同一文件夹中的.exe / .dll),如可通过这段代码可以看出:
The file does indeed exist (in the same folder as the .exe/.dll), as can be seen by this code:
// test with smaller file:
fileName = "DSD_v6666_3_20140310140737916.xml";
MessageBox.Show("Made it before file.Open");
using (FileStream fileTest = File.Open(fileName, FileMode.CreateNew))
{
fileTest.Write(info, 0, info.Length);
fileTest.Flush();
}
if (!File.Exists(fileName))
{
MessageBox.Show(String.Format("{0} does not seem to exist", fileName));
}
else
{
MessageBox.Show(String.Format("{0} DOES seem to exist", fileName));
}
string justFileName = Path.GetFileNameWithoutExtension(fileName);
String uri = String.Format(@"http://SHANNON2:21609/api/inventory/sendXML/gus/woodrow/{0}", justFileName).Trim();
SendXMLFile(fileName, uri, 500);
下面是代码,然后将其称为,试图发送的文件:
Here is the code that is then called, attempting to send the file:
public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
// TODO: Remove after testing
String s = String.Format("xmlFilepath == {0}, uri == {1}, timeout == {2}", xmlFilepath, uri, timeout);
MessageBox.Show(s);
// </ TODO: Remove after testing
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
//request.KeepAlive = false; // should this be true? <== commented out as a test, but no diff in behavior
request.ProtocolVersion = HttpVersion.Version10;
request.ContentType = "application/xml";
request.Method = "POST";
StringBuilder sb = new StringBuilder();
// TODO: Remove after testing
MessageBox.Show("Made it to just before the StreamReader using");
using (StreamReader sr = new StreamReader(xmlFilepath))
{
// TODO: Remove after testing
MessageBox.Show("Made it just inside the StreamReader using"); // <= This is the last point reached
String line;
while ((line = sr.ReadLine()) != null)
{
// TODO: Remove after testing
MessageBox.Show(string.Format("line == {0}", line));
sb.Append("\r\n");
}
. . .
当我运行它,我看到:
"Made it before file.Open"
"DSD_v6666_3_20140310140737916.xml DOES seem to exist"
[The xmlFilepath, uri, and timout vals expected]
"Made it to just before the StreamReader using"
"Made it just inside the StreamReader using"
- 但不是的<em>行== ... 的消息 - 它挂起,我必须热启动装置,使其从电子回冷宫
-- but not the "line == ..." message - it hangs, and I have to warm boot the device to bring it back from electronic limbo.
是否存在与StreamReader的代码中潜在的问题,还是... ???
Is there a potential problem with the StreamReader code, or...???
我不知道这是否是一个问题是数据或差异我的代码,使得到它在紧凑型框架。我有非常类似的代码,从WinForms应用程序的工作原理:
I don't know whether this is a problem is in the data, or a differences I had to make in the code to get it to work in the Compact Framework. I have very similar code that works from a Winforms app:
public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.ContentType = "application/xml";
request.Method = "POST";
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(xmlFilepath))
{
String line;
while ((line = sr.ReadLine()) != null)
{
sb.AppendLine(line);
}
byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());
if (timeout < 0)
{
request.ReadWriteTimeout = timeout;
request.Timeout = timeout;
}
request.ContentLength = postBytes.Length;
try
{
Stream requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
//using (var response = (HttpWebResponse)request.GetResponse())
//{
// return response.ToString();
//}
// alternate way, safe for older versions of .NET
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)request.GetResponse();
}
finally
{
IDisposable disposableResponse = response as IDisposable;
if (disposableResponse != null) disposableResponse.Dispose();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
request.Abort();
return string.Empty;
}
}
}
---被称为像这样,传递同一个文件作为测试用例:
---called like so, passing the same file as a test case:
private void button20_Click(object sender, EventArgs e)
{
// Change the file name before each test
String fullFilePath = @"C:\HoldingTank\DSD_v6666_3_20140310140737916.xml";
string justFileName = Path.GetFileNameWithoutExtension(fullFilePath);
String uri = String.Format(@"http://localhost:21608/api/inventory/sendXML/su/su/{0}", justFileName);
SendXMLFile(fullFilePath, uri, 500);
}
更新2
我改变了代码使用一个XmlTextReader,现在我回到我以前有,即犯错这是在其最血腥的细节的here 。
下面是新的代码,我现在看到的:
Here is the new code, and what I now see:
公共静态布尔WriteIt2(字符串文件名,字符串数据,长FSIZE )
{
布尔retVal的= FALSE;
INT bytRd = 0; //如果用这个,更改其名称
串the_Msg =;
public static bool WriteIt2( string fileName, string data, long fsize ) { bool retVal = false; int bytRd = 0; // if use this, change its name string the_Msg = "";
if (File.Exists(fileName))
{
File.Delete(fileName);
}
Byte[] info = Encoding.UTF8.GetBytes(data);
// Testing with this relatively small file for now
fileName = "DSD_v6666_3_20140310140737916.xml";
MessageBox.Show("Made it before file.Open");
using (FileStream fileTest = File.Open(fileName, FileMode.CreateNew))
{
fileTest.Write(info, 0, info.Length);
fileTest.Flush();
}
if (!File.Exists(fileName))
{
MessageBox.Show(String.Format("{0} does not seem to exist", fileName));
} // I have never seen the msg above, but always saw the one below, so commented it out
else //<= always exists, so unnecessary
{
MessageBox.Show(String.Format("{0} DOES seem to exist", fileName));
}
string justFileName = Path.GetFileNameWithoutExtension(fileName);
String uri = String.Format(@"http://SHANNON2:21609/api/inventory/sendXML/su/su/{0}", justFileName).Trim();
SendXMLFile(fileName, uri, 500);
现在这里是实际执行的阅读,写作和发送(或尝试)的代码:
Now here's the code that actually does the reading, writing, and sending (or tries to):
public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
String s = String.Format("xmlFilepath == {0}, uri == {1}, timeout == {2}", xmlFilepath, uri, timeout);
MessageBox.Show(s);
// </ TODO: Remove after testing
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.ProtocolVersion = HttpVersion.Version10;
request.ContentType = "application/xml";
request.Method = "POST";
StringBuilder sb = new StringBuilder();
MessageBox.Show("Made it to just before the StreamReader using");
StreamReader sr = new StreamReader(xmlFilepath);
MessageBox.Show("Made it past the StreamReader being constructed");
XmlTextReader reader = null;
reader = new XmlTextReader(sr);
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element: // The node is an Element.
sb.Append("<" + reader.Name);
while (reader.MoveToNextAttribute()) // Read attributes.
sb.Append(" " + reader.Name + "='" + reader.Value + "'");
sb.Append(">");
sb.Append(">");
break;
case XmlNodeType.Text: //Display the text in each element.
sb.Append (reader.Value);
break;
case XmlNodeType. EndElement: //Display end of element.
sb.Append("</" + reader.Name);
sb.Append(">");
break;
}
}
// TODO: Remove after testing
MessageBox.Show("Made it past the while loop");
MessageBox.Show(String.Format("sb first line is {0}", sb[0].ToString()));
MessageBox.Show(String.Format("sb tenth line is {0}", sb[9].ToString()));
byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());
if (timeout < 0)
{
request.Timeout = timeout;
}
request.ContentLength = postBytes.Length;
try
{
Stream requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
// This code for older versions of .NET from ctacke:
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)request.GetResponse();
return response.ToString();
}
finally
{
IDisposable disposableResponse = response as IDisposable;
if (disposableResponse != null) disposableResponse.Dispose();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
request.Abort();
return string.Empty;
}
}
我现在看到当这个运行:
What I see now when this runs:
0) "Made it before file.Open"
1) "DSD_v6666_3_20140310140737916.xml DOES seem to exist"
2) [ the xmlFilePath and other args - they are what is expected ]
3) "Made it to just before the StreamReader using"
4) "Made it past the StreamReader being constructed
5) "Made it past the while loop
6) "sb first line is "<"
7) "sb tenth line is ">"
8) "The remote server returned an error (400) Bad Request"
因此,在至少它不再挂,但我回不知道为什么服务器认为这是一个错误的请求。
So at least it's no longer hanging, but I'm back to wondering why the server considers this a bad request.
推荐答案
我想你应该返朴归真:
public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
using (var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/xml");
byte[] response = client.UploadFile(uri, "POST", xmlFilepath);
return Encoding.ASCII.GetString(response);
}
}
和看看有什么效果和服务器认为一个什么样的文件。
and see what works and what the server thinks of your file.
当你真的需要一个超时则见这个答案
When you really need a TimeOut then see this answer
这篇关于为什么这个代码挂在从一个StreamReader达到第一的ReadLine?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!