Help threading HttpWebRquest in c# - c#

Hi guys just wondering if somebody could help me try and correctly thread my application, I am constantly hitting an hurdle after another, I have never been to clued up on threading in applications. I have tryed following this http://www.developerfusion.com/code/4654/asynchronous-httpwebrequest/ tutorial.
basically I'm just trying to stop my request from hanging my application
public class Twitter
{
private const string _username = "****",
_password = "****";
private WebResponse webResp;
public string getTimeLine()
{
Thread thread = new Thread(new ThreadStart(TwitterRequestTimeLine));
thread.IsBackground = true;
thread.Start();
using (Stream responseStream = webResp.GetResponseStream())
{
//
using (StreamReader reader = new StreamReader(responseStream))
{
return reader.ReadToEnd();
}
}
}
private void TwitterRequestTimeLine()
{
string aUrl = "http://168.143.162.116/statuses/home_timeline.xml";
HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create(aUrl);
SetRequestParams(request);
request.Credentials = new NetworkCredential(_username, _password);
//WebResponse tempResp = request.GetResponse();
ThreadState state = new ThreadState();
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(???), ???);
}
private static void SetRequestParams( HttpWebRequest request )
{
request.Timeout = 500000;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.UserAgent = "AdverTwitment";
}
}
}
anyone help would be greatly appricated

You really don't need to thread HttpWebRequest.
When you use BeginGetResponse() and EndGetResponse() with HttpWebRequest, it already uses a background thread for you in order to work asynchronously. There is no reason to push this into a background thread.
As for usage: The help for HttpWebRequest.BeginGetResponse demonstrates a complete, asynchronous request.

If this is a WinForms app, the easiest way to keep the GUI responsive while executing the WebRequest is to use a BackgroundWorker component. Drop a BackgroundWorker on your form and call its RunWorkAsync() method. Put the code to execute the WebRequest and read the Response in the DoWork event handler.

Try using an AsyncCallback like Rubens suggested but have the callback call into a separate method to load the data to its destination. If the getTimeline method doesn't return immediately it will cause the application to hang, because the UI Thread is what is running the request itself.
If you use a separate AsyncCallback to be called after the request is done and have it load the data then the method will return immediately and your UI thread can do other things while it waits.

What about this:
private string getTimeLine()
{
string responseValue = "";
string aUrl = "http://168.143.162.116/statuses/home_timeline.xml";
AutoResetEvent syncRequest = new AutoResetEvent(false);
WebRequest request = WebRequest.Create(aUrl);
request.Method = "POST";
request.BeginGetResponse(getResponseResult =>
{
HttpWebResponse response =
(HttpWebResponse)request.EndGetResponse(getResponseResult);
using (StreamReader reader =
new StreamReader(response.GetResponseStream()))
{
responseValue = reader.ReadToEnd();
}
syncRequest.Set();
}, null);
syncRequest.WaitOne();
return responseValue;
}
EDIT: Ok, I tried to keep a method returning a string, that's why I used AutoResetEvent; If you use a BackgroundWorker, you'll get notified when your data is available:
BackgroundWorker worker = new BackgroundWorker();
string responseValue = "";
worker.RunWorkerCompleted += (sender, e) =>
{
// update interface using responseValue variable
};
worker.DoWork += (sender, e) =>
{
string aUrl = "http://168.143.162.116/statuses/home_timeline.xml";
WebRequest request = WebRequest.Create(aUrl);
// .. setup
using(StreamReader reader =
new StreamReader(request.GetResponse().GetResponseStream()))
responseValue = reader.ReadToEnd();
};
worker.RunWorkerAsync();

Related

How do I prevent httpwebrequest opening a new tcp connection for each PUT request?

Whenever I have to PUT a json string to a server, I launch a new thread which has this code inside a class. It works fine, but the thing is that a TCP connection is opened for each request. When I checked the ServicePoint hashcode, its the same for each request.
When I looked in TCPView, I cannot find those connections - I think its because its opened and closed within ~50ms.
So, 2 questions -
Is it an issue if I leave it like this? A new request will be raised every second from the client.
How do I reuse the same TCP connection? What if I set ServicePoint.KeepAlive to true?
public void SendRequest()
{
string sOutput="";
try
{
HttpWebRequest myWebRequest = (HttpWebRequest)WebRequest.Create(_uri);
myWebRequest.Timeout = Timeout;
myWebRequest.ReadWriteTimeout = Timeout;
myWebRequest.ContentType = "application/json";
myWebRequest.Method = "PUT";
myWebRequest.Proxy = WebRequest.GetSystemWebProxy();
ServicePointManager.CheckCertificateRevocationList = true;
using (StreamWriter myStreamWriter = new StreamWriter(myWebRequest.GetRequestStream()))
{
myStreamWriter.Write(_json);
}
using (HttpWebResponse myWebResponse = (HttpWebResponse)myWebRequest.GetResponse())
{
using (StreamReader myStreamReader = new StreamReader(myWebResponse.GetResponseStream()))
{
sOutput = myStreamReader.ReadToEnd();
sOutput = sOutput.Length == 0 ? myWebResponse.StatusDescription : sOutput;
ServicePoint currentServicePoint = myWebRequest.ServicePoint;
sOutput = currentServicePoint.GetHashCode().ToString();
currentServicePoint.ConnectionLimit = 5;
}
}
}
catch (Exception Ex)
{
sOutput = Ex.Message;
}
finally
{
callback?.Invoke(sOutput);
}
}
And here is how I launch the thread -
HTTPClass hTTPClass = new HTTPClass(cuURI, json, 5000, new MyCallback(ResultCallBack));
Thread t = new Thread(new ThreadStart(hTTPClass.SendRequest));
t.Start();
Here is the code after switching to HttpClient -
static HttpClient client = new HttpClient();
public async Task Write()
{
await WriteAsync(cuURI, json);
}
private async Task WriteAsync(Uri uri, string json)
{
StringContent content = new StringContent(json,Encoding.UTF8,"application/json");
await client.PutAsync(uri, content);
}
Here is the wireshark trace screenshot which shows a new connection for every request.
The client is setting the FIN flag on its own, and the server is not sending a FIN from its side. What is happening is that I see a lot of connections in the TIME_WAIT state on the server side.

GetResponse not coming back using HttpWebRequest

Using form contenttype, I am getting stuck at this line:
var webresponse = (HttpWebResponse)webrequest.GetResponse();
For the url, you can use any value. Here is the full code:
public bool test()
{
string url = "https://www.google.com";
// Create a new HTTP request object, set the method to POST and write the POST data to it
var webrequest = (HttpWebRequest)WebRequest.CreateHttp(url);
webrequest.Method = "POST";
webrequest.ContentType = "application/x-www-form-urlencoded";
using (Stream postStream = webrequest.GetRequestStream())
{
//
}
// Make the request, get a response and pull the data out of the response stream
var webresponse = (HttpWebResponse)webrequest.GetResponse();
Stream responseStream = webresponse.GetResponseStream();
var reader = new StreamReader(responseStream);
string result = reader.ReadToEnd();
// Normal Completion
return true;
}
Does anyone know why it would get stuck on this line and not come back (when you are doing debugging):
var webresponse = (HttpWebResponse)webrequest.GetResponse();
Thank You
I found the problem! I was calling the method as an async task:
private async Task starttest()
{
clsTester objTester = new clsTester();
objTester.test();
}
...
var result = Task.Run(async () => await starttest());
I removed all that code and changed it to a worker thread:
private Thread workerThread = null;
private void starttest()
{
clsTester objTester = new clsTester();
objTester.test();
}
And then called it as follows:
...
// Initialise and start worker thread
this.workerThread = new Thread(new ThreadStart(this.starttest));
this.workerThread.Start();
Everything is working now.

How can I prevent UI freezing while using HttpWebRequest?

I have a progressBar on my form and a button.
When user clicks this button, the progressBar should be styled as "marquee" and the program begins to check is an URL is valid or not.. OK.
But when I click the button, the UI freezes until the HttpStatusCode returns true or false...
Here is the check code:
private bool RemoteFileExists(string url)
{
try
{
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "HEAD";
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
return (response.StatusCode == HttpStatusCode.OK);
}
catch
{
return false;
}
}
And here is the button click code:
private async void button1_Click(object sender, EventArgs e)
{
this.progressBar1.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
var result = RemoteFileExists("http://www.google.com/");
if (Completed)
{
//ok
}
else
{
//not ok
}
}
The UI freezes because you are executing the RemoteFileExists method on the UI thread and receiving a response from a HttpWebRequest takes some time.
To solve this you have to execute RemoteFileExists in a different thread than the UI thread.
As your button1_Click method is already declared async the easiest way would be to declare RemoteFileExists as async too.
Then you can use the HttpWebRequest.GetResponseAsync method to asynchronously receive the response object.
private async Task<bool> RemoteFileExists(string url)
{
try
{
HttpWebRequest request = WebRequest.CreateHttp(url);
request.Method = "HEAD";
using(var response = (HttpWebResponse) await request.GetResponseAsync())
{
return (response.StatusCode == HttpStatusCode.OK);
}
}
catch
{
return false;
}
}
Also when dealing with IDisposables you should take care of releasing all used resources by using the using statement or calling Dispose().
If you are using .NET Framework 4+ you can also use WebRequest.CreateHttp(string) to create your HttpWebRequest.
Putting it simple just use this:
private void button1_Click(object sender, EventArgs e)
{
this.progressBar1.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
Thread thread = new Thread(() => RemoteFileExists("http://www.google.com/"));
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
And do the check inside RemoteFileExists .

Watin multithreading issue

I have a problem in my application, written in c# using WatiN.
The application creates few threads,and each thread open browser and the same page.
The page consist of HTML select element: and a submit button.
The browsers should select a specific option and click on the submit button at the same time but instead they do it "one by one".
Here is the main code lines:
[STAThread]
static void Main(string[] args)
{
for (int i = 0; i < numOfThreads;i++ )
{
var t = new Thread(() => RealStart(urls[i]));
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();
}
}
private static void RealStart(string url)
{
using (var firstBrowser = new IE())
{
firstBrowser.GoTo(url);
firstBrowser.BringToFront();
OptionCollection options = firstBrowser.SelectList("Select").Options;
options[1].Select();
firstBrowser.Button(Find.ByName("Button")).Click();
firstBrowser.Close();
}
}
What is the cause of the "one by one" selection instead of simultaneously selection?
Solution:
After a long research I gave up using WatiN for this porpuse.
Instead, I have created HttpWebRequest and post it to the specific URL.
Works Like a charm:
HttpWebRequest httpWReq = (HttpWebRequest)WebRequest.Create("http://domain.com/page.aspx");
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = "username=user";
postData += "&password=pass";
byte[] data = encoding.GetBytes(postData);
httpWReq.Method = "POST";
httpWReq.ContentType = "application/x-www-form-urlencoded";
httpWReq.ContentLength = data.Length;
using (Stream stream = httpWReq.GetRequestStream())
{
stream.Write(data,0,data.Length);
}
HttpWebResponse response = (HttpWebResponse)httpWReq.GetResponse();
string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
I send those requests simultaneously, by creating a Thread for each request.

How wait asynchronous method in a thread?

I need that Join method is called when Download.file method have finished.
I tried to add await keyword but it didn't work
Thread myThread = new Thread(new ThreadStart(()=> await Download.file(uri)));
Thread myThread = new Thread(new ThreadStart(()=>Download.file(uri)));
myThread.Start();
myThread.Join();
class Download{
public static async void file(string url)
{
try
{
HttpWebRequest request;
HttpWebResponse webResponse = null;
request = HttpWebRequest.CreateHttp(url);
request.AllowReadStreamBuffering = true;
webResponse = await request.GetResponseAsync() as HttpWebResponse;
Stream responseStream = webResponse.GetResponseStream();
using (StreamReader reader = new StreamReader(responseStream))
{
string content = await reader.ReadToEndAsync();
}
webResponse.Close();
}
catch (Exception ex) {
Debug.WriteLine(ex.Message);
}
}
}
Thanks
You should make your file method (which is badly named, by the way - it should probably be something like DownloadFileAsync) return Task instead of void.
Then you can await it.
However, it's not clear why you're starting this in a different thread anyway - the point of asynchrony is that you don't need to start a new thread. From another async method, you can just use:
await Download.file(uri);
(Of course the fact that the method isn't doing anything with the content is a little strange...)
You should also consider using HttpClient or WebClient, both of which have this behaviour already available.

Categories