0

I am working on bot technology, in one of my projet i wrote below lines of code

private async void DeliveryProgressReport(IDialogContext context, Activity message)
    {
        MessagesController.progressdetails = SQLDatabaseService.getinprogressdetails();
        var progress = MessagesController.progressdetails;
        if (progress.Count > 0)
        {
            try
            {
                Activity replyToConversation = message.CreateReply("**In Progress Report Details**");
                replyToConversation.Recipient = message.From;
                replyToConversation.Type = "message";
                replyToConversation.Attachments = new List<Attachment>();
                Dictionary<string, string> progresslist = new Dictionary<string, string>();
                foreach (var progressreport in progress)
                {

                    //Invoke the machine learning model for predicting the delivery status of delivery person
                    //var deliveryStatus= await InvokeRequestResponseServiceOfDeliveryPersonPredictionExp1();
                    //await Task.Delay(TimeSpan.FromSeconds(5));
                    var deliveryStatus = await InvokeRequestResponseServiceOfDeliveryPersonPredictionExp(progress[0].Name, progress[0].Mobile_Number);

                    progresslist.Add(progressreport.Name, progressreport.Mobile_Number);
                    List<CardImage> cardImages = new List<CardImage>();
                    cardImages.Add(new CardImage(url: progressreport.Photo_Url));
                    ThumbnailCard tlcard = new ThumbnailCard()
                    {
                        Title = "Name:" + progressreport.Name,
                        Subtitle = "Call:" + progressreport.Mobile_Number,
                        Images = cardImages,
                        Text = "Staus by Using Machine Learning Prediction:" + deliveryStatus
                    };
                    Attachment plAttachment = tlcard.ToAttachment();
                    replyToConversation.Attachments.Add(plAttachment);
                }
                replyToConversation.AttachmentLayout = AttachmentLayoutTypes.List;
                await context.PostAsync(replyToConversation);
            } catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
        else
        {
            Activity replyToConversation = message.CreateReply("**There are no in progress deliveries are found**");
            await context.PostAsync(replyToConversation);
        }

    }

    private async Task<string> InvokeRequestResponseServiceOfDeliveryPersonPredictionExp(string name, string mobile_Number)
    {
         string status = "";
        //Func<Stream, Task> copyStreamAsync = async stream =>
        //{
        //await Task.Factory.StartNew(async () =>
        //{
        //using (stream)
        //using (var sourceStream = await sourceContent.Content.ReadAsStreamAsync())
        //{
        //    await sourceStream.CopyToAsync(stream);
        //}

        //var client = new HttpClient();
        using (var client = new HttpClient())
        {
            var scoreRequest = new
            {

                Inputs = new Dictionary<string, StringTable>() {
            {
                "input1",
                new StringTable()
                {
                    ColumnNames = new string[] {"Id", "Name", "Mobile_Number", "CourierCompany_Name", "Status", "EmailId"},
                    Values = new string[,] {  { "", name, mobile_Number, "", "","" }, { "", name, mobile_Number, "", "", "" }, }
                }
            },
        },
                GlobalParameters = new Dictionary<string, string>()
                {
                }
            };
            const string apiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx=="; // Replace this with the API key for the web service
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);

            client.BaseAddress = new Uri("My Request URL");

            // WARNING: The 'await' statement below can result in a deadlock if you are calling this code from the UI thread of an ASP.Net application.
            // One way to address this would be to call ConfigureAwait(false) so that the execution does not attempt to resume on the original context.
            // For instance, replace code such as:
            //      result = await DoSomeTask()
            // with the following:
            //      result = await DoSomeTask().ConfigureAwait(false)
            //var status = await PostRequest(scoreRequest,client).ConfigureAwait(false);

            HttpResponseMessage response = await client.PostAsJsonAsync("", scoreRequest);//.ConfigureAwait(false);

            string correctLocation = "";
            string wrongLocation = "";
            string notReached = "";
            string personMismatch = "";
            if (response.IsSuccessStatusCode)
            {
                string result = await response.Content.ReadAsStringAsync();

                var results = JsonConvert.DeserializeObject<RootObject>(result);

                foreach (var value in results.Results.output1.value.Values)
                {

                    status = value[8].ToString();
                    correctLocation = value[4].ToString();
                    notReached = value[5].ToString();
                    personMismatch = value[6].ToString();
                    wrongLocation = value[7].ToString();
                }


                Debug.WriteLine("Result: {0}", result);
                return status;
            }
            else
            {
                Debug.WriteLine(string.Format("The request failed with status code: {0}", response.StatusCode));

                // Print the headers - they include the requert ID and the timestamp, which are useful for debugging the failure
                Debug.WriteLine(response.Headers.ToString());

                string responseContent = await response.Content.ReadAsStringAsync();
                Debug.WriteLine(responseContent);
                return status;

            }
        };
        // return status;
    }

After executing this below line I got the exception like asynchronous module or handler completed while an asynchronous operation was still pending

await context.PostAsync(replyToConversation);

Before posting this question I had followed through this below links, but I didn't resolve it.

Async Void, ASP.Net, and Count of Outstanding Operations

Web Api + HttpClient: An asynchronous module or handler completed while an asynchronous operation was still pending

Please tell how to resolve this exception.

-Pradeep

Community
  • 1
  • 1
Pradeep
  • 5,101
  • 14
  • 68
  • 140
  • So what kind of recommendation you are looking for (beyond "don't use `async void` in ASP.Net" from links you've added)? – Alexei Levenkov Sep 28 '16 at 18:21
  • Return a `Task` instead of `Void` in DeliveryProgressReport. `Void` can lead to unexpected outcome – Mrinal Kamboj Sep 28 '16 at 18:22
  • I already tried using Task instead of void in DeliveryProgressReport. at that time I got the empty value when ever execute the below method. var deliveryStatus = await InvokeRequestResponseServiceOfDeliveryPersonPredictionExp(progress[0].Name, progress[0].Mobile_Number); – Pradeep Sep 28 '16 at 18:25
  • That you need to debug and understand, since it must be genuinely returning the Empty Value. Also like void, Task has no return value – Mrinal Kamboj Sep 28 '16 at 18:36
  • when I m debugging this method private async Task InvokeRequestResponseServiceOfDeliveryPersonPredictionExp(string name, string mobile_Number) { ---code-- } I got the 500 internal server error after executing the below line in the above method. HttpResponseMessage response = await client.PostAsJsonAsync("", scoreRequest);//.ConfigureAwait(false); – Pradeep Sep 28 '16 at 18:42
  • Are you using `ConfigureAwait(false)` anywhere, why, you want to ignore the Ui / Caller context ? – Mrinal Kamboj Sep 29 '16 at 06:08

1 Answers1

2

Finally, I resolved the above exception when I am return Task instead of void in DeliveryProgressReport method. and also where ever I was called the await DeliveryProgressReport() method there also I return Task instead of void.

-Pradeep

Pradeep
  • 5,101
  • 14
  • 68
  • 140
  • For Async-Await void return is only for events, shouldn't be used anywhere else, as expected void was suppressing and issue a destabilizing the system – Mrinal Kamboj Sep 29 '16 at 06:08