Question Async C# code not executing in async manner

Dhruvil

Member
Joined
Dec 19, 2020
Messages
12
Programming Experience
3-5
I have created a C# wrapper for my Ax 2012 AIF Service which is triggered from power automate. There is a limitation in power automate that the gateway times out in 110 seconds. So, my requirement is to call my C# wrapper in async manner and get response immediately and not wait for any response ( Since, I am not aware of using polling in this ) and handled any error if occurs in AX 2012 side by creating entries in log table.

The main issue was that even after using async, the flow waited for the response of the async function. Not only that, it was executing my AX code twice in parallel. First execution gets stopped as my flow times out and the second one continues even after it. I had inserted lines in my table and due to parallel execution, they were created 2 times even though I was updating it if found already.

This is my C# code for that :

C#:
//It dynamically sets the AIF Url and calls the method to consume AIF services
using SXA_FlowIntegrationWebAPI.Helpers;
using SXA_FlowIntegrationWebAPI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace SXA_FlowIntegrationWebAPI.Controllers
{
    public class MainController : ApiController
    {
        [ActionName("Method")]
        [HttpPost]
        [Authorize]
        public IHttpActionResult CallMethod(ClassMethodCallRequest request)
        {
            dynamic retValue;

                using (var client = new AX2012.SXAFlowIntegrationServiceClient())
                {
                    try
                    {
                        var callContext = new AX2012.CallContext();
                        callContext.Company = request.companyId;
                        callContext.LogonAsUser = User.Identity.Name;

                        client.InnerChannel.OperationTimeout = new TimeSpan(0, 10, 00);
                        client.Endpoint.Address = new System.ServiceModel.EndpointAddress(request.aifURL);
                       
                        if (request.methodName == "insertUpdatePurchOrderAsync")
                        {
                            retValue = "";
                            CallMethodAsyncCustom(client, callContext, request);
                        }
                     
                        else
                        {
                            retValue = client.callMethod(callContext, request.className, request.methodName, request.dataJsonStr);
                        }
                    }
                    catch (Exception e)
                    {
                        return Json(new ClassMethodCallResponse
                        {
                            status = "Error",
                            userName = User.Identity.Name,
                            className = request.className,
                            methodName = request.methodName,
                            aifURL = request.aifURL,
                            error = e
                        });
                    }
                }

            return Json(new ClassMethodCallResponse
            {
                status = "Success",
                userName = User.Identity.Name,
                className = request.className,
                methodName = request.methodName,
                aifURL = request.aifURL,
                data = retValue,
            });
        }

        public static System.Threading.Tasks.Task<SXA_FlowIntegrationWebAPI.AX2012.SXAFlowIntegrationServiceCallMethodResponse> callMethodAsyncNew(AX2012.SXAFlowIntegrationServiceClient client,SXA_FlowIntegrationWebAPI.AX2012.CallContext CallContext, string _className, string _methodName, string _data)
        {
            SXA_FlowIntegrationWebAPI.AX2012.SXAFlowIntegrationServiceCallMethodRequest inValue = new SXA_FlowIntegrationWebAPI.AX2012.SXAFlowIntegrationServiceCallMethodRequest();
            inValue.CallContext = CallContext;
            inValue._className = _className;
            inValue._methodName = _methodName;
            inValue._data = _data;
            return ((SXA_FlowIntegrationWebAPI.AX2012.SXAFlowIntegrationService)(client)).callMethodAsync(inValue);
        }

        public static async void CallMethodAsyncCustom(AX2012.SXAFlowIntegrationServiceClient client2, AX2012.CallContext callContext, ClassMethodCallRequest request)
        {
            var client = new AX2012.SXAFlowIntegrationServiceClient();
            try
            {
                client.Open();
                client.InnerChannel.OperationTimeout = new TimeSpan(0, 10, 00);
                client.Endpoint.Address = new System.ServiceModel.EndpointAddress(request.aifURL);
                client.Endpoint.Binding.SendTimeout = new TimeSpan(0, 10, 00);
                client.Endpoint.Binding.ReceiveTimeout = new TimeSpan(0, 20, 00);
                await System.Threading.Tasks.Task.Run( () =>  callMethodAsyncNew(client, callContext, request.className, request.methodName, request.dataJsonStr));
                //Console.WriteLine(x.response);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            finally
            {
                client.Close();
            }

        }
    }

}


I want a way that it returns my JSON before completing the async method. Also the 2 parallel executions should be avoided and only one should be executed until the end.
 
Last edited:

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
4,431
Location
Chesapeake, VA
Programming Experience
10+
Run the async part in another thread, AND DO NOT wait on the results.
 

Dhruvil

Member
Joined
Dec 19, 2020
Messages
12
Programming Experience
3-5
So do you mean instead of await System.Threading.Tasks.Task.Run( () => callMethodAsyncNew(client, callContext, request.className, request.methodName, request.dataJsonStr));
I should use System.Threading.Tasks.Task.Run( () => callMethodAsyncNew(client, callContext, request.className, request.methodName, request.dataJsonStr)); ?
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
4,431
Location
Chesapeake, VA
Programming Experience
10+
Which will almost bring you back full circle to your other thread. :)

You'll need to do an await within the lambda, but not await the Task created by Task.Run().
 
Top Bottom