Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Stream not Writable" error when using StreamWriter in loop

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?

like image 522
MacHume Avatar asked Aug 21 '15 19:08

MacHume


2 Answers

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

}

like image 198
NotMe Avatar answered Sep 22 '22 17:09

NotMe


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.

like image 37
ryachza Avatar answered Sep 20 '22 17:09

ryachza