Reputation: 73
I'm trying to write a tool in C# to help QA some network issues, and am running into a problem. The program is supposed to send a query in JSON format to the server every second.
Currently, it works once, but on the second attempt to send the query, I get an exception because the
"Stream was not writable."
Here's my code:
public partial class Form1 : Form
{
Timer timer1;
String query;
String result;
HttpWebRequest request;
StreamWriter writeData;
StreamReader readData;
HttpWebResponse response;
public Form1()
{
InitializeComponent();
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 1000;
File.Delete(AppDomain.CurrentDomain.BaseDirectory + "log.txt");
logOutput.ReadOnly = true;
request = (HttpWebRequest)WebRequest.Create("a URL goes here");
request.ContentType = "application/json";
request.Method = "POST";
query = "{some json stuff goes here}";
}
private void startButton_Click(object sender, EventArgs e)
{
if (!timer1.Enabled)
{
timer1.Start();
startButton.Text = "Stop";
}
else
{
timer1.Stop();
startButton.Text = "Start";
}
}
private void timer1_Tick(object sender, EventArgs e)
{
writeData = new StreamWriter(request.GetRequestStream());
writeData.Write(query);
writeData.Flush();
writeData.Close();
response = (HttpWebResponse)request.GetResponse();
readData = new StreamReader(response.GetResponseStream());
result = readData.ReadToEnd();
logOutput.Text = result;
File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + "log.txt", result + "\r\n");
}
}
}
Anyone know what I'm doing wrong?
Upvotes: 6
Views: 9407
Reputation: 175
Similar issue causes if you do not reinitialize the request. As mentioned by ryachza i have pushed request initialization inside loop and it worked for me.
foreach (String item in DATA)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "POST";
request.ContentType = "application/json";
using (Stream webStream = request.GetRequestStream())
using (StreamWriter requestWriter = new StreamWriter(webStream, System.Text.Encoding.ASCII))
{
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
Object routes_list =
json_serializer.DeserializeObject(item);
requestWriter.Write(item);
}
WebResponse webResponse = request.GetResponse();
using (Stream webStream = webResponse.GetResponseStream() ?? Stream.Null)
using (StreamReader responseReader = new StreamReader(webStream))
{
response.Add(responseReader.ReadToEnd());
}
}
Upvotes: 0
Reputation: 88044
First off, Stop with the global variables. Move the streamwriter
, streamreader
, httpwebresponse
etc into the actual tick method.
Anything that implements IDisposable
, which most of that stuff does, should be very local variables that aren't hanging around and are wrapped up in using
clauses.
Basically your request object is closed out once your method has finished.
Something like this will work a LOT better:
private void timer1_Tick( object sender, EventArgs e ) {
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("a URL goes here");
request.ContentType = "application/json";
request.Method = "POST";
String query = "{some json stuff goes here}";
String result = String.Empty;
using ( StreamWriter writeData = new StreamWriter(request.GetRequestStream()) ) {
writeData.Write(query);
writeData.Flush();
using ( HttpWebResponse response = (HttpWebResponse)request.GetResponse() ) {
using ( StreamReader readData = new StreamReader(response.GetResponseStream()) ) {
result = readData.ReadToEnd();
}
}
}
logOutput.Text = result;
File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + "log.txt", result + "\r\n");
}
}
Upvotes: 4
Reputation: 4540
So I presume it's the writeData.Write(query)
that's throwing? request.GetRequestStream()
should only be writeable until the request is actually sent, which I believe is done when you call request.GetResponse()
. So it works on the first tick, but then sends the request and can't write the second time.
Are you trying to send the request multiple times? You would need to reinitialize the request object.
Upvotes: 1