Click here to Skip to main content
14,389,400 members
Rate this:
Please Sign up or sign in to vote.
See more:
Hello ,
I am trying to create an asp.net web api. This API will be called from a scheduler from cloud once every 15 minute where this API will look in db and Call an external third party web-service multiple times with different parameters.External service will just return true of false.

I am fairly new to async programming. I don't even know what i am doing is right and if so , is it the correct way to do it. I have read many articles and gone through multiple same questions on stack overflow but couldn't find the answer.

Some article says it's not good to use task in webapi , some says use parallel prog some say don't use parallel prog on server. i am confused. Please tell me the correct way to use async prog at server.

What I have tried:

public void FindSessionAndInitiateCall()
       {
           using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
           {
               using (SqlCommand cmd = new SqlCommand())
               {
                   cmd.CommandType = CommandType.StoredProcedure;
                   cmd.CommandText = "sp_FindSessionsToConnect";
                   SqlDataReader dr = cmd.ExecuteReader();
                   while (dr.Read())
                   {
                       CreateRequest(dr["ManagerMob"].ToString(), dr["EmployeeMob"].ToString(), dr["SessionDuration"].ToString(), dr["SlotId"].ToString());
                   }
               }
           }
       }

       private async Task<string> CreateRequest( string ManagerMob,string EmployeeMob, string SessionDuration, string SlotId)
       {
           HttpWebRequest request;
           var result = "";
           try
           {
               string URL = "*******************";
               request = (HttpWebRequest)WebRequest.Create(URL);
               request.Method = "POST";
               WebResponse response = await request.GetResponseAsync();
               //HttpWebResponse response = (HttpWebResponse)request.GetResponse();
               using (StreamReader reader = new StreamReader(response.GetResponseStream()))
               {
                   var objText = reader.ReadToEnd();
                   var root = JObject.Parse(objText);
                   result = root["msg"].ToString();
               }
               response.Close();
               return result;
           }
           catch (Exception ex)
           {
               return ex.Message;
           }


       }
Posted
Updated 27-Sep-17 6:23am

1 solution

Rate this:
Please Sign up or sign in to vote.

Solution 1

You're creating a series of Task objects, but never waiting for them to complete. The calling method will return before the work has finished. And if any of the tasks fails, it could end up taking down your entire process with an "unobserved exception" error.

You should make the FindSessionAndInitiateCall method async, and have it return a Task. You will then be able to wait for all of the child tasks to complete, and the caller will be able to wait for the work to finish.

You might also find it easier to use the HttpClient[^] class instead of the raw WebRequest class; HttpClient was designed to be async-friendly from the start, whereas the task-returning methods on the WebRequest were added long after its creation.

Your code also needs to set the command's connection property, and open the connection before trying to execute the command.
public async Task FindSessionAndInitiateCall(CancellationToken cancellationToken = default(CancellationToken))
{
    List<Task> tasks = new List<Task>();
    
    using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
    using (SqlCommand cmd = new SqlCommand("sp_FindSessionsToConnect", con))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        
        con.Open();
        using (SqlDataReader dr = cmd.ExecuteReader())
        {
            while (dr.Read())
            {
                Task<string> request = CreateRequest(
                    dr.Field<string>("ManagerMob"), 
                    dr.Field<string>("EmployeeMob"), 
                    dr.Field<string>("SessionDuration"), 
                    dr.Field<string>("SlotId"),
                    cancellationToken);
                
                tasks.Add(request);
            }
        }
    }
    
    // Wait for all requests to complete:
    await Task.WhenAll(tasks).ConfigureAwait(false);
}


// Avoid creating new instances of the HttpClient where possible.
// See: http://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
private static readonly HttpClient Http = new HttpClient();

private async Task<string> CreateRequest(string ManagerMob, string EmployeeMob, string SessionDuration, string SlotId, CancellationToken cancellationToken)
{
    const string URL = "*******************";
    
    var parameters = new Dictionary<string, string>
    {
        ["ManagerMob"] = ManagerMob,
        ["EmployeeMob"] = EmployeeMob,
        ["SessionDuration"] = SessionDuration,
        ["SlotId"] = SlotId,
    };
    
    var content = new FormUrlEncodedContent(parameters);
    
    var response = await Http.PostAsync(URL, content, cancellationToken);
    if (!response.IsSuccessStatusCode)
    {
        return string.Format("{0}: {1}", response.StatusCode, response.ReasonPhrase);
    }
    
    string objText = await response.Content.ReadAsStringAsync(cancellationToken);
    var root = JObject.Parse(objText);
    return root["msg"].ToString();
}

You're using HttpClient wrong and it is destabilizing your software | ASP.NET Monsters[^]
   
Comments
Charlie Andrews 28-Sep-17 3:27am
   
Thank you Richard :) Read the articles provided . It was very helpfull

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100