0
public void RemoteInsert()  
{
        String dataSet = "dataset=" + json.ToString();  
        accessKey = mobRemoteDB.accessKey;  
        String paramaters = "?llcommand=sndmsg&" + "ak=" + accessKey +   "&command=remoteinsert&" + dataSet;  
        String url = mobRemoteDB.baseUrlForRemoteInsert + paramaters;
        HttpWebRequest webRequest = (HttpWebRequest)System.Net.WebRequest.Create(url);    
        webRequest.Method = "POST";    
        webRequest.ContentType = "application/json";  
       if (NetworkInterface.GetIsNetworkAvailable() & IsDataValid)  
        {
         webRequest.BeginGetRequestStream(newAsyncCallback(GetRequestStreamCallback),webR equest); 
        }  
}  

void GetRequestStreamCallback(IAsyncResult asynchronousResult)
    {
        HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;           
        webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest);            
    }


 void GetResponseCallback(IAsyncResult asynchronousResult)
    {
        try
        {                
            HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
            HttpWebResponse response = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult);
            Stream streamResponse = response.GetResponseStream();
            StreamReader streamReader = new StreamReader(streamResponse);
            JObject json_response = JObject.Parse(streamReader.ReadToEnd());
            String key = (String)json_response["ret"];
            JObject dic = (JObject)json_response["retdic"];
         }
         catch(WebException e)
         {
         }
    }

I want RemoteInsert() method to wait for my callback GetResponseCallback. I am Unable to do that as tried many things.
Can any body Please Assist me here. I do not want the main thread to work something else until this response comes . Please Suggest.
as after that response i have to use it for next execution.

Here My code is going like 
1. Task(A).running----await 
2.   ------------------------------->Task(B)
3                              ---------Response From Task(A)------->Task(C)

I want to Implement it like First Task A Completes , Then Task(C) as it is on Success of Task(A). Then Task(B)

Cœur
  • 37,241
  • 25
  • 195
  • 267
Sonu
  • 132
  • 1
  • 12
  • Have you tired using webRequest.GetRequestStream() instead of .BeginGetRequestStream() ? - You mention you've 'tried many things'. It would be helpful to know what you've tried. – olitee Jan 23 '15 at 09:37
  • I've tried EventWaitHandle insertionDone = new EventWaitHandle(false, EventResetMode.ManualReset); then insertionDone.WaitOne(); to wait . But application was in a deadlockCondition even after setting signalinsertionDone1.Set(); where response is received and there is no webRequest.GetRequestStream() Method – Sonu Jan 23 '15 at 09:39

1 Answers1

3

If I understand your question, you're wanting to perform the webrequest on the calling thread, and wait for it to complete before continuing?

You can simplify your RemoteInsert() method by using async/await, and using the GetResponseAsync() method to fetch the response object in one call. Something like this:

public async Task RemoteInsert()
{
    String dataSet = "dataset=" + json.ToString();
    accessKey = mobRemoteDB.accessKey;
    String paramaters = "?llcommand=sndmsg&" + "ak=" + accessKey + "&command=remoteinsert&" + dataSet;
    String url = mobRemoteDB.baseUrlForRemoteInsert + paramaters;
    HttpWebRequest webRequest = (HttpWebRequest)System.Net.WebRequest.Create(url);
    webRequest.Method = "POST";
    webRequest.ContentType = "application/json"; 

    if (NetworkInterface.GetIsNetworkAvailable() && IsDataValid)
    {
        // Await the GetResponseAsync() call.
        using(var response = await webRequest.GetResponseAsync().ConfigureAwait(false))
        {
            // The following code will execute on the main thread.
            using (var streamResponse = response.GetResponseStream())
            {
                using (StreamReader streamReader = new StreamReader(streamResponse))
                {
                    JObject json_response = JObject.Parse(streamReader.ReadToEnd());
                    String key = (String)json_response["ret"];
                    JObject dic = (JObject)json_response["retdic"];
                }
            }
        }
    }
}

And lose the other two methods, as they're no longer required.

When you call this method, you can Wait() on it:

RemoteInsert().Wait();

However, WP tries to enforce good async patterns to avoid doing this. What is your need to block the UI thread in this case?

In your method that is calling RemoteInsert() ... lets assume it's some kind of button-click event ... can you not do this?

public async void Button_Click()
{
    // First call Remote insert, and await the result.
    // The web-request will not block the UI thread.
    await RemoteInsert();

    // This code will be executed after RemoteInsert() completes:
    ... perform additional tasks that are dependant on RemoteInsert()
}

In other words, rather than blocking the UI thread - you execute those other methods AFTER the RemoteInsert() method has completed.

olitee
  • 1,683
  • 10
  • 12
  • Hello Olitee, The .NET compilation for Windows Phone contains an implementation of the WebRequest class which does not have synchronous methods for obtaining request stream and response, as these would block execution on the UI thread until the operations completed. You can use the existing Begin/End methods directly with callback delegates as i refered this link http://stackoverflow.com/questions/18816990/webrequest-has-no-getresponse-method-windows-phone-8 – Sonu Jan 23 '15 at 10:05
  • Sorry, didn't spot the Windows Phone bit. Surely WP has the `.GetResponseAsync()` method? I've edited my answer to make the entire RemoteInsert() method `async`, and now `await` on the `GetResponseAsync()` call. This call will be asynchronous, but the following code will wait for the response, and then execute on the main thread. – olitee Jan 23 '15 at 10:11
  • hello olitee , Thanks for your answer but I want to make this call syncronous and want main thread to wait for this response. As i have other actions in parallel to it which starts executing on main thread , which i do not want. – Sonu Jan 23 '15 at 10:16
  • OK. I've updated my answer to show a blocking solution ... but it doesn't smell right. It sounds like those parallel tasks shouldn't be executed until RemoteInsert() is complte ... which is something you can easily achieve with async/await, and NO blocking of the UI thread. – olitee Jan 23 '15 at 10:26
  • Hello Olitee , RemoteInsert().Wait(); this way is blocking it permanently . application stops for atleast 10 mins it is being idle. There is no response. – Sonu Jan 23 '15 at 10:42
  • And there is no .Result Method in this . – Sonu Jan 23 '15 at 10:50
  • @Sonu OK, I've tidied up some of the code by properly disposing of the webresponse and stream objects. That may have been blocking your code. The missing .Result() method was a typo ... I fixed that too. – olitee Jan 23 '15 at 10:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/69438/discussion-between-sonu-and-olitee). – Sonu Jan 23 '15 at 11:05
  • @Sonu I'm afraid chat is blocked on the network I'm using. :( – olitee Jan 23 '15 at 11:06
  • ok olitee, But your this method didn't worked too. Do we have to Return any task like return await Task.Factory.StartNew (() => {}); – Sonu Jan 23 '15 at 11:07
  • Not if you're using the `async` keyword, no. Which method are you trying to use? The first one using `await`, or the second one using `.Result`? I really think the solution to your problem is outside of this method - you need to look at how you're executing those parallel tasks. Are those tasks dependant on the result (completion) of the RemoteInsert() method? – olitee Jan 23 '15 at 11:11
  • Yes I am afarid to say that Task are dependent on Result(Completion ). – Sonu Jan 23 '15 at 11:23
  • I've tried to clarify things in the answer, and made a suggestion about the method that calls your RemoteInsert() method. I've tested the code here, and the webrequest/response/stream code runs ok (using GET instead of POST for testing). Are you getting any exceptions when running? – olitee Jan 23 '15 at 11:41
  • @Sonu Just spotted a deadlock bug - fixed it with adding `.ConfigureAwait(false)` ... sorry I didn't spot that earlier. That is probably the cause of the deadlock situation you experienced with `RemoteInsert().Wait();` – olitee Jan 23 '15 at 11:48
  • Hey Olitee at your end it will work good as after task completion your other tasks will be executed . But think of a scenario that i have two tasks Task(A) and Task(B) on a button click . But on Completion of task a We have some on success events and there is another action Task(C). Here My code is going like 1. Task(A).running----await 2. ------------------------------->Task(B) 3 ---------Response From Task(A)------->Task(C) I want to Implement it like First Task A Completes , Then Task(C) as it is on Success of Task(A). Then Task(B) – Sonu Jan 24 '15 at 04:49
  • 1
    It sounds like you want these tasks to run sequentially, but on background threads? Is that correct? If so, then you simply need to await each task in the order you need them. – olitee Jan 27 '15 at 09:38