Blocking asynchronous operation in Windows phone - c#

I am trying send the http post from the windows phone to the server and I am getting some of problem via sending the post data.I put the break point in button_click_1 function and I found that it would not start the asynronous operation. Beside that, it also block the current thread and I know that this situation is cause by the allDone.waitOne().
Why the asynronous operation will not function and how to solve it?
Thank you for any help.
private void Button_Click_1(object sender, RoutedEventArgs e)
{
// Create a new HttpWebRequest object.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
// start the asynchronous operation
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
allDone.WaitOne();
}
Asynronous operation:
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
Stream postStream = request.EndGetRequestStream(asynchronousResult);
string postData = "xxxxxxxxxxx";
// Convert the string into a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Write to the request stream.
postStream.Write(byteArray, 0, postData.Length);
postStream.Close();
// Start the asynchronous operation to get the response
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
tbtesting.Text = responseString.ToString();
streamResponse.Close();
streamRead.Close();
response.Close();
allDone.Set();
}

You're not the first to hit this (see Is it possible to make synchronous network call on ui thread in wpf (windows phone)). If you do this then you deadlock the UI thread on Windows Phone.
The closest you're going to get is to use the async/await on your network calls. There are extension methods you can use to do this as part of the Microsoft.Bcl.Async package on NuGet.

Related

WindowsPhone HttpWebRequest to ashx WebService

I have a problem with HttpWebRequest:
I have an ashx code in a visual studio ws that simply does:
public void ProcessRequest(HttpContext context)
{
var a = context.Request.Form["a"];
var b = context.Request.Form["b"];
context.Response.Write(a + " " + b);
}
I tried to call it with advancedRestClient and it worked, but if i call it with my windows phone device I get a not found exception and the request doesn't reach any breakpoint.
this is my WP code:
public void PostIt2()
{
string url = "http://localhost/blablacode/ecc.ashx";
// Create a new HttpWebRequest object.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "application/x-www-form-urlencoded";
// Set the Method property to 'POST' to post data to the URI.
request.Method = "POST";
// start the asynchronous operation
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
// Keep the main thread from continuing while the asynchronous
// operation completes. A real world application
// could do something useful such as updating its user interface.
allDone.WaitOne();
}
private static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
Stream postStream = request.EndGetRequestStream(asynchronousResult);
string postData = "{'a': 'avar','b':'bvar'}";
// Convert the string into a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Write to the request stream.
postStream.Write(byteArray, 0, postData.Length);
postStream.Close();
// Start the asynchronous operation to get the response
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
Console.WriteLine(responseString);
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
allDone.Set();
}
I took the code from MSDN so i don't know what i'm doing wrong, i also tried a lot of methods found on the internet, the only thing important for me is that i have to use HttpWebRequest and not HttpClient.
Can someone help me please?
Its possible that the problem is not in the code.
Are your services accesible from the phone??
Are your proyect configure with internet access??
If all its ok, look at this post:
httpclient postasync windows phone 8.1 universal app second call 404 error
Ok, really thanks god is friday.
i was using as url "localhost/eccecc.ashx"
device's localhost is not same localhost of computer.

Flow of execution in Httpwebrequest POST in Windows hone 8

If I have this code in Windows Phone 8, for instance
string __retS = null;
private String postRequest(String url, String postData)
{
byte[]byteData = Encoding.UTF8.GetBytes(postData);
HttpWebRequest request = null;
try
{
Uri uri = new Uri(url);
request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteData.Length;
// start the asynchronous operation
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
} // end try
catch (Exception)
{
}
return __retS;
}
I put a breakpoint on this line request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);. I expected that execution will jump to my GetRequestStreamCallback method but it doesn't. It rather goes on to execute the return statement hence a null value is always returned.
Is that how its supposed to go?
Is that how its supposed to go?
Yes. When the work is done it will invoke the callback function you passed. See "Asynchronous Programming Model (APM)". Starting with .Net 4.5 / c# 5.0, you can use async/await which can help to write async codes simpler.
var stream = await request.GetRequestStreamAsync();
//...do some work using that stream
The callback is executed asynchronously, that means the code is continued after the asynchronous method is assigned. (request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);)
When the WebRequest is finished, the GetRequestStreamCallback is executed.
Because the UI thread would be blocked if this request was synchronous the windows phone sdk only serves an asynchronous one.

Windows Phone 7 Consume Webservice JSON data

I am now just learning Windows Phone 7 development, I am using C#, as this is the language I am the most familiar with.
For now, I would like to create the following flow: user type something in a text field and press a button -> i show him a "Please wait" message box and send the text field text to a WebService (maybe over HTTPS), when the WebService response is received I will show him another screen, bases on the response data.
This WebService retrieves only JSON data, so I need to parse JSON data.
I think I am already able to send data and retrieve the response from the server, however, I dont know how to show this "loading" message box, hide it when dode, and start a new screen (blocking the access to this first one).
On button click:
HttpWebRequest wr = (HttpWebRequest)System.Net.WebRequest.Create("http://example.com/");
wr.Method = "POST";
wr.ContentType = "application/x-www-form-urlencoded";
wr.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), wr);
GetRequestStreamCallback method:
void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest wr = (HttpWebRequest)asynchronousResult.AsyncState;
Stream postStream = wr.EndGetRequestStream(asynchronousResult);;
byte[] byteArray = Encoding.UTF8.GetBytes("key=" + someText.Text);
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
wr.BeginGetResponse(new AsyncCallback(GetResponseCallback), wr);
}
GetResponseCallback method:
void GetResponseCallback(IAsyncResult asynchronousResult)
{
try
{
HttpWebRequest wr = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)wr.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamReader = new StreamReader(streamResponse);
MessageBox.Show(streamReader.ReadToEnd()); // ???
streamReader.Close();
streamResponse.Close();
response.Close();
}
catch (WebException e)
{
// Does nothing
}
}
Whatever method you use for progress indication, turn it on right before the call to the service, myProgressIndicator.Show = true; then in the callback and when done with any other processing, turn it off, myProgressIndicator.Show = false;. Don't forget to turn it off in the catch for exception handling as well.
Coding4Fun has a progress overlay.

Login to mediawiki by api on wp7

I am trying to create an app for wp7 to login to wikipedia and help with translating the pages.
I am stuck right at the beginning since I can't get it to login through the mediawiki API.
The relevant part of the code goes like this:
data.Append("action=login&lgname" + HttpUtility.UrlEncode(textBox1.Text));
data.Append("&lgpassword=" + HttpUtility.UrlEncode(passwordBox1.Password));
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback),request);
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
public void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
Stream postStream = request.EndGetRequestStream(asynchronousResult);
byte[] byteData = UTF8Encoding.UTF8.GetBytes(data.ToString());
postStream.Write(byteData, 0, data.Length);
postStream.Close();
}
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
streamResponse.Close();
streamRead.Close();
response.Close();
}
The problems are:
On the GetRequestStreamCallback I can't pass the data string from the main function. How do I do this?
On the GetResponseCallback function how do I return the responsestring String so that I can output later?
What you're actually trying to do is two asynchronous operations, one after another - it's worth remembering that the BeginXxx methods return before they've finished - so in your case, you ask for the request stream to write to, and immediately ask for the response, so bad things will ensue.
It's possibly worth looking at other examples, such as those in opensource code - you'll see that you don't typically call BeginGetResponse until you've finished writing to the stream returned by EndGetRequestStream

NullReferenceException reading from an asynchronous HttpWebRequest stream

I'm programming an application for Windows Phone 7. This application firstly sends, and then receives data from a server via HttpWebRequest. Most times it works fine, but sometimes, after receiving a portion of the data properly, I get a NullReferenceException in Stream.Read() function.
The communication starts when the user presses a button. Then I create the HttpWebRequest:
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(sUri);
request.Method = "POST";
request.BeginGetRequestStream(GetRequestStreamCallback, request);
The request callback method:
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
postStream = request.EndGetRequestStream(asynchronousResult);
this.bSyncOK = Send(); //This is my method to send data to the server
postStream.Close();
if (this.bSyncOK)
request.BeginGetResponse(GetResponseCallback, request);
else
manualEventWait.Set(); //This ManualResetEvent notify a thread the end of the communication, then a progressbar must be hidden
}
The response callback method:
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult) )
{
using (streamResponse = new StreamReader(response.GetResponseStream() ) )
{
this.bSyncOK = Recv(); //This is my generic method to receive the data
streamResponse.Close();
}
response.Close();
}
manualEventWait.Set(); //This ManualResetEvent notify a thread the end of the communication, then a progressbar must be hidden
}
And finally, this is the code where I get the exception reading the stream data:
int iBytesLeidos;
byte[] byteArrayUTF8 = new byte[8];
iBytesLeidos = streamResponse.BaseStream.Read(byteArrayUTF8, 0, 8); //NullReferenceException!!! -Server always send 8 bytes here-
When the application starts, I create a background thread that frequently sends info to the server. Background and Manual communications can run simultaneously. Could this be a problem?
Thanks.
If streamResponse is global variable, it can cause the problem in a case of an access from another thread. Pass your Stream to the Recv as a parameter
using (StreamReader streamResponse = new StreamReader(response.GetResponseStream() ) )
{
this.bSyncOK = Recv(streamResponse); //This is my generic method to receive the data
streamResponse.Close();
}
Where is your streamResponse declared in latter snippet? Is it the same object as in 3d snippet? Maybe you just use another variable, instead of actual stream.
in the second snippet, try to delete "postStream.Close();".

Categories

Resources