用于多个API调用的Asp.net MVC4并行编程

时间:2016-08-18 15:24:35

标签: c# asp.net-mvc multithreading asp.net-mvc-4 parallel-processing

我有一些关于ASP .NET MVC 4并行编程的问题。 我想使用并行编程,因为同时从多个API调用接收数据。

以下是一些小例子

RootObjectRS fairsearchRS1 = new RootObjectRS();
RootObjectRS fairsearchRS2 = new RootObjectRS();
RootObjectRS fairsearchRS3 = new RootObjectRS();

fairsearchRS1 = MakeRequest(searchUrl, WWWToken, request.TripType1, request.TripfromAirPort1, request.TriptoAirPort1, request.FlyfromDate1, request.FlytoDate1, request.Flyclass, request.Passengers, starting, reqstid);        
fairsearchRS2 = MakeRequest(searchUrl, WWWToken, request.TripType2, request.TripfromAirPort2, request.TriptoAirPort2, request.FlyfromDate2, request.FlytoDate2, request.Flyclass, request.Passengers, starting, reqstid);        
fairsearchRS3 = MakeRequest(searchUrl, WWWToken, request.TripType3, request.TripfromAirPort3, request.TriptoAirPort3, request.FlyfromDate3, request.FlytoDate3, request.Flyclass, request.Passengers, starting, reqstid);

这只是我的代码的一个小例子。使用make请求我正在调用这些API,并从中获取数据并将其绑定到那些rootobjectRS对象。

现在我一个接一个地发送这些请求。但我需要同时这样做,我需要等到这3个请求数据到达。

那么我应该如何使用并行或其他编程方法来解决这个问题呢? 因为现在需要1分钟。但如果我同时这样做,那么我可以在20秒内完成。这是节省时间的主要因素。

我不知道ASP .NET MVC4是否可以实现这种并行编程概念。但如果有人可以给我支持,那将是很有帮助的。至少一些好的教程也很有帮助。

修改

实际上这是我的makeRequest函数,

 public static RootObjectRS MakeRequest(string requestUrl, SeneruUBT.Models.TokenModels token, string triptype, string from, string to, string flyin, string flyout, string flyclass, string passengers, DateTime starting, int reqstid)
        {

            HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
            request.Method = "POST";
            request.ContentType = "application/json";
            request.Headers.Add("Authorization", token.token_type + " " + token.access_token);
            request.Accept = "application/json";

            string ttrip = triptype;

            var streamWriter = new StreamWriter(request.GetRequestStream());

            if (ttrip.Equals("OneWay"))
            {
                RootObject searchBFMRQO = CreateRequestObjectOneWay(triptype, from, to, flyin, flyclass, passengers);
                String searchString = JsonConvert.SerializeObject(searchBFMRQO);
                streamWriter.Write(JsonConvert.SerializeObject(searchBFMRQO));

                streamWriter.Flush();
            }
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            var httpResponse = (HttpWebResponse)request.GetResponse();
            int sc = (int)httpResponse.StatusCode;
            System.Diagnostics.Debug.Write(sc);
            if (httpResponse.StatusCode != HttpStatusCode.OK)
            {

                using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                {
                    var result = streamReader.ReadToEnd();
                    RootObjectRS errorresult = JsonConvert.DeserializeObject<RootObjectRS>(result);

                    return (errorresult);
                }
            }
            else
            {
                var resp = new StreamReader(httpResponse.GetResponseStream()).ReadToEnd();

                RootObjectRS searchResponse = JsonConvert.DeserializeObject<RootObjectRS>(resp.ToString());

                SearchResponseFlightService ResponsFlSer = null;
                ResponsFlSer = new SearchResponseFlightService(new UBTRepository.UBTUnitofWorks(new UBTRepository.TravelEntities()));
                SearchResponseFlight ReFl = new SearchResponseFlight();


                ReFl.searchRequestID = reqstid;
                ReFl.StopQuantity = "1";
                ReFl.responseJson = resp.ToString();
                DateTime ending = DateTime.Now;
                ReFl.responseDuration = ending.Subtract(starting).Milliseconds;
                ReFl.starttimestamp = starting;

                ReFl.endtimestamp = ending;

                ResponsFlSer.Add(ReFl);

                searchResponse.reqid = reqstid;

                return (searchResponse);
            }


        }

我认为现在可能有点容易理解。

将我的make请求更改为异步后它不起作用 - 在MakeRequestAsync中给出错误。

 public static async Task RootObjectRS MakeRequestAsync(string requestUrl, SeneruUBT.Models.TokenModels token, string triptype, string from, string to, string flyin, string flyout, string flyclass, string passengers, DateTime starting, int reqstid)
    {

        HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
        request.Method = "POST";
        request.ContentType = "application/json";
        request.Headers.Add("Authorization", token.token_type + " " + token.access_token);
        request.Accept = "application/json";

        string ttrip = triptype;

        var streamWriter = new StreamWriter(await request.GetRequestStreamAsync());

        if (ttrip.Equals("OneWay"))
        {
            RootObject searchBFMRQO = CreateRequestObjectOneWay(triptype, from, to, flyin, flyclass, passengers);
            String searchString = JsonConvert.SerializeObject(searchBFMRQO);
            streamWriter.Write(JsonConvert.SerializeObject(searchBFMRQO));

            streamWriter.Flush();
        }
        HttpWebResponse response = await (HttpWebResponse)request.GetResponseAsync();
        var httpResponse = await (HttpWebResponse)request.GetResponseAsync();
        int sc = (int)httpResponse.StatusCode;
        System.Diagnostics.Debug.Write(sc);

            var resp = new StreamReader(await httpResponse.GetResponseStreamAsync()).ReadToEnd();

            RootObjectRS searchResponse = JsonConvert.DeserializeObject<RootObjectRS>(resp.ToString());

            SearchResponseFlightService ResponsFlSer = null;
            ResponsFlSer = new SearchResponseFlightService(new UBTRepository.UBTUnitofWorks(new UBTRepository.TravelEntities()));
            SearchResponseFlight ReFl = new SearchResponseFlight();


            ReFl.searchRequestID = reqstid;
            ReFl.StopQuantity = "1";
            ReFl.responseJson = resp.ToString();
            DateTime ending = DateTime.Now;
            ReFl.responseDuration = ending.Subtract(starting).Milliseconds;
            ReFl.starttimestamp = starting;

            ReFl.endtimestamp = ending;

            ResponsFlSer.Add(ReFl);

            searchResponse.reqid = reqstid;

            return (searchResponse);



        }

2 个答案:

答案 0 :(得分:0)

您想首先将MakeRequest修改为MakeRequestAsync。基本上,只要该方法访问某些I / O操作,Microsoft就会提供异步版本。 (阅读下面的文章,了解它的作用)

public static async Task<RootObjectRS> MakeRequestAsync(string requestUrl, SeneruUBT.Models.TokenModels token, string triptype, string from, string to, string flyin, string flyout, string flyclass, string passengers, DateTime starting, int reqstid)
    {

        HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
        request.Method = "POST";
        request.ContentType = "application/json";
        request.Headers.Add("Authorization", token.token_type + " " + token.access_token);
        request.Accept = "application/json";

        string ttrip = triptype;

        var streamWriter = new StreamWriter(await request.GetRequestStreamAsync());

        if (ttrip.Equals("OneWay"))
        {
            RootObject searchBFMRQO = CreateRequestObjectOneWay(triptype, from, to, flyin, flyclass, passengers);
            String searchString = JsonConvert.SerializeObject(searchBFMRQO);
            streamWriter.Write(JsonConvert.SerializeObject(searchBFMRQO));

            streamWriter.Flush();
        }
        HttpWebResponse response = await (HttpWebResponse)request.GetResponseAsync();
        var httpResponse = await (HttpWebResponse)request.GetResponseAsync();
        int sc = (int)httpResponse.StatusCode;
        System.Diagnostics.Debug.Write(sc);
        if (httpResponse.StatusCode != HttpStatusCode.OK)
        {

            using (var streamReader = new StreamReader(await httpResponse.GetResponseStreamAsync()))
            {
                var result = streamReader.ReadToEnd();
                RootObjectRS errorresult = JsonConvert.DeserializeObject<RootObjectRS>(result);

                return (errorresult);
            }
        }
        else
        {
            var resp = new StreamReader(await httpResponse.GetResponseStreamAsync()).ReadToEnd();

            RootObjectRS searchResponse = JsonConvert.DeserializeObject<RootObjectRS>(resp.ToString());

            SearchResponseFlightService ResponsFlSer = null;
            ResponsFlSer = new SearchResponseFlightService(new UBTRepository.UBTUnitofWorks(new UBTRepository.TravelEntities()));
            SearchResponseFlight ReFl = new SearchResponseFlight();


            ReFl.searchRequestID = reqstid;
            ReFl.StopQuantity = "1";
            ReFl.responseJson = resp.ToString();
            DateTime ending = DateTime.Now;
            ReFl.responseDuration = ending.Subtract(starting).Milliseconds;
            ReFl.starttimestamp = starting;

            ReFl.endtimestamp = ending;

            ResponsFlSer.Add(ReFl);

            searchResponse.reqid = reqstid;

            return (searchResponse);
        }


    }

上面的方法可以使用一些重构(其中有很多内容=))

现在MakeRequestAsync存在,请修改下面的代码。

RootObjectRS fairsearchRS1 = new RootObjectRS();
RootObjectRS fairsearchRS2 = new RootObjectRS();
RootObjectRS fairsearchRS3 = new RootObjectRS();

var fairsearchRS1Task = MakeRequestAsync(searchUrl, WWWToken, request.TripType1, request.TripfromAirPort1, request.TriptoAirPort1, request.FlyfromDate1, request.FlytoDate1, request.Flyclass, request.Passengers, starting, reqstid);        
var fairsearchRS2Task = MakeRequestAsync(searchUrl, WWWToken, request.TripType2, request.TripfromAirPort2, request.TriptoAirPort2, request.FlyfromDate2, request.FlytoDate2, request.Flyclass, request.Passengers, starting, reqstid);        
var fairsearchRS3Task = MakeRequestAsync(searchUrl, WWWToken, request.TripType3, request.TripfromAirPort3, request.TriptoAirPort3, request.FlyfromDate3, request.FlytoDate3, request.Flyclass, request.Passengers, starting, reqstid);

fairsearchRS1 = await fairsearchRS1Task;
fairsearchRS2 = await fairsearchRS2Task;
fairsearchRS3 = await fairsearchRS3Task;    

注意:您不想做像Task.Run这样的事情。这将创建一个新线程。见摘录:

&#34; async和await关键字不会导致创建其他线程。异步方法不需要多线程,因为异步方法不能在自己的线程上运行。该方法在当前同步上下文上运行,并仅在方法处于活动状态时在线程上使用时间。您可以使用Task.Run将受CPU限制的工作移动到后台线程,但后台线程对于等待结果可用的进程没有帮助。&#34;

来自:https://msdn.microsoft.com/en-us/library/mt674882.aspx

启动新线程,IIS托管应用程序是不好的做法。请参阅:https://blogs.msdn.microsoft.com/tmarq/2010/04/14/performing-asynchronous-work-or-tasks-in-asp-net-applications/

答案 1 :(得分:-1)

    var tasks = new Task[] {
        Task.Run(() => MakeRequest()),
        Task.Run(() => MakeRequest()),
        Task.Run(() => MakeRequest())
        };

    Task.WaitAll(tasks);

Task.Run可能不是应用异步模式的合适方法。找到为三个长时间运行的呼叫执行ansync模式的正确方法。