如何显示异步结果哪一个是先在asp.netweb应用程序? [英] How to display the Asynchronous results which one is first in asp.netweb application?

查看:184
本文介绍了如何显示异步结果哪一个是先在asp.netweb应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要送三个类文件的三个非同步的请求,3请求的响应时间是不同的,第一个是2秒和第二个是7秒和第三个是4秒,现在我要显示在浏览器中的第一反应在2秒2秒和之后显示第三响应,最后显示第二反应,,但现在我的成绩都在反应完成后三个响应时间显示,请给我任何建议,这是非常紧迫的,请... ..

I have to send three asynch requests in three class files, 3 requests response times are different, first one is 2sec and second one is 7sec and third one is 4sec , now i have to display first response in browser with in 2sec and after 2sec display the third response and finally display the second response , but now my results all responses display at a time after completed three responses, please give me any suggestion, it is very urgent, please.....

我的code是

public delegate string AsyncMethodCaller(string name);
        public delegate string AsyncMethodCallertest(string name);
        public delegate string NatilusAsyn(string name);

按钮单击事件

     AsyncMethodCaller caller = new AsyncMethodCaller(ps.PennStarService);
        IAsyncResult result = caller.BeginInvoke(txtFirst.Text, null, null);
    NatilusAsyn caller123 = new NatilusAsyn(cs.PennStarService);
        IAsyncResult result123 = caller123 .BeginInvoke(txtthird.Text, null, null);
        AsyncMethodCallertest cltest = new AsyncMethodCallertest(ps.testHi);
        IAsyncResult tetsresult = cltest.BeginInvoke(txtSecond.Text, null, null);
        lblFirst.Text = caller.EndInvoke(result);           
        lblSecond.Text = cltest.EndInvoke(tetsresult);
     lblthird.Text = caller123.EndInvoke(result123); 

感谢ü
hemanth

thank u hemanth

推荐答案

我觉得问题的根源是理解与ASP.Net的请求会发生什么。

I think the root of the problem is to understand what happens with an ASP.Net request.

每个页面都有其生命周期,其中包括事件的管道,以获取更多信息检查这个答案。每个请求由一个工作线程从当前应用程序的AppDomain中处理。直至页面管道完成响应将不被发送给用户。

Each page has its life-cycle which includes a pipeline of events, for more information check this answer. Each request is handled by a worker thread from the AppDomain of the current application. The response won't be sent to the user until the page pipeline is completed.

关于主题:

同时可用线程的数量可以在的machine.config 进行配置。关键的一点要明白的是,这些数量的线程是固定的,这意味着当已达到并发线程的最大数目,后续请求将被放置在队列中,可以放置在队列中的请求的数量仅由服务器的存储器中的限制。

The number of simultaneous available threads can be configured in the machine.config. The key point to understand is that these number of threads are fixed, which means that when the max number of simultaneous threads has been reached, subsequent requests will be placed in a queue, the number of requests that can be placed in the queue are only limited by the memory of the server.

当一个工人线程调用一个长期耗时的操作,您是阻塞线程,直到操作完成,这又意味着,如果有多个并发用户,潜在的所有可用线程可能被阻塞,迫使新的要求是放置在队列中,并在最坏的情况下,引起503错误 - 服务不可

When a worker thread calls a long time-consuming operation, you are blocking that thread, until the operation finishes, which means again, if there are several concurrent users, potentially all available threads could be blocked, forcing new requests to be placed in a queue and in the worst case, causing a 503 error - Service Unavailable.

该办法prevent这是通过调用这些种在后台线程的方法。 类似的code ,但该行为是不是你期待什么在这种情况下,您的code正在等待的线程,以便最终为完成页面请求这就是你在同一时间接收结果(在请求结束)的原因。

The way to prevent this is by calling these kind of methods in background threads. Similar to your code, but the behavior is not what you are expecting in this case, your code is waiting for the threads to end in order to finish the page request that's the reason you are receiving the result at the same time (at the end of the request).

有关执行asp.net页面异步的参阅本优秀的文章

For more details about executing asp.net pages asynchronously, refer to this excellent article

现在,为了得到你想要的结果:

Now in order to get the results you need:

(这是一个完整的工作的例子,在这个例子中,我使用接收 - 反应式编程运行在一个新的线程耗时长的方法,你可以改变这如果你喜欢使用另一个框架,我用$接收,因为我感觉更舒服的API p $ PFER)

(This is a full working example, in this example, I am using Rx - Reactive Programming to run long time-consuming methods in a new thread, you can change this to use another framework if you like, I prefer using Rx because I feel more comfortable with the API)

    [WebMethod]
    public static string Execute1()
    {
        JavaScriptSerializer j = new JavaScriptSerializer();
        string r = string.Empty;
        var o = Observable.Start(() =>
            {
                Thread.Sleep(2000);
                r = "My Name1: " + DateTime.Now.ToString() + " Background thread: " + Thread.CurrentThread.ManagedThreadId.ToString();
            }, Scheduler.NewThread);
        o.First();
        r += " Main thread: " + Thread.CurrentThread.ManagedThreadId.ToString();
        r = j.Serialize(new { res = r });
        return r;
    }

    [WebMethod]
    public static string Execute2()
    {
        JavaScriptSerializer j = new JavaScriptSerializer();
        string r = string.Empty;
        var o = Observable.Start(() =>
        {
            Thread.Sleep(7000);
            r = "My Name2: " + DateTime.Now.ToString() + " Background thread: " + Thread.CurrentThread.ManagedThreadId.ToString();
        }, Scheduler.NewThread);
        o.First();
        r += " Main thread: " + Thread.CurrentThread.ManagedThreadId.ToString();
        r = j.Serialize(new { res = r });
        return r;
    }

    [WebMethod]
    public static string Execute3()
    {
        JavaScriptSerializer j = new JavaScriptSerializer();
        string r = string.Empty;
        var o = Observable.Start(() =>
        {
            Thread.Sleep(4000);
            r = "My Name3: " + DateTime.Now.ToString() + " Background thread: " + Thread.CurrentThread.ManagedThreadId.ToString();
        }, Scheduler.NewThread);
        o.First();
        r += " Main thread: " + Thread.CurrentThread.ManagedThreadId.ToString();
        r = j.Serialize(new { res = r });
        return r;
    }

ASPX

....
<script type="text/javascript" src="Scripts/jquery-1.7.2.min.js"></script>
....
<asp:ScriptManager runat="server" />
<input type="button" id="callAsync" name="callAsync" value="Call Async" />
<div id="first"></div>
<script type="text/javascript">
    function onsuccess1(msg) {
        var result = Sys.Serialization.JavaScriptSerializer.deserialize(msg.d);
        var h = $("#first").html();
        $("#first").html( h + "<br/>&nbsp;&nbsp;&nbsp;&nbsp;Result: " + result.res);
    }
    function onerror1(xhr) {
        alert(xhr.responseText);
    }
    function callMyMethod(url, mydata, onsuccess, onerror) {
        var h = $("#first").html();
        $("#first").html(h + "<br/>&nbsp;&nbsp;Calling Method: " + new Date());
        return $.ajax({
            cache: false,
            type: "POST",
            async: true,
            url: url,
            data: mydata, 
            contentType: "application/json",
            dataType: "json",
            success: function (msg) {
                onsuccess(msg);
            },
            error: function (xhr) {
                onerror(xhr);
            }
        });
    }
    $(document).ready(function () {
        $("#callAsync").click(function () {
            var h = $("#first").html();
            $("#first").html(h + "<br/>New call: " + new Date());
            callMyMethod("DynamicControls.aspx/Execute1", "{}", function (data) { onsuccess1(data); }, function (data) { onerror1(data); });
            callMyMethod("DynamicControls.aspx/Execute2", "{}", function (data) { onsuccess1(data); }, function (data) { onerror1(data); });
            callMyMethod("DynamicControls.aspx/Execute3", "{}", function (data) { onsuccess1(data); }, function (data) { onerror1(data); });
        });
    });
</script>

输出

这code生成以下内容:

Output

This code generates the following:

New call: Fri Jun 22 02:11:17 CDT 2012
  Calling Method: Fri Jun 22 02:11:17 CDT 2012
  Calling Method: Fri Jun 22 02:11:17 CDT 2012
  Calling Method: Fri Jun 22 02:11:17 CDT 2012
    Result: My Name1: 6/22/2012 2:11:19 AM Background thread: 38 Main thread: 48
    Result: My Name2: 6/22/2012 2:11:26 AM Background thread: 50 Main thread: 48
    Result: My Name3: 6/22/2012 2:11:30 AM Background thread: 52 Main thread: 48

正如你可以看到code未优化,主线程被锁定,以秒为最大数,我们设置了7个,但在这种情况下,从时间服务器code被称为(二时11分17秒),直到接收到最后的响应(2点11分30秒)。13秒钟以后。这是因为ASP.Net默认锁电流会话对象锁定在主线程。因为我们没有在这个例子中使用环节中,我们可以配置页面是这样的:

As you can see the code is not optimized, the main thread is being locked, the max number of seconds we set up are 7 but in this case, from the time the server code was called (02:11:17) until the last response received (2:11:30) 13 seconds elapsed. This is because ASP.Net by default locks the current Session object locking the main thread. Since we are not using the session in this example, we can configure the page like this:

<%@ Page EnableSessionState="False"

和新的输出是:

New call: Fri Jun 22 02:13:43 CDT 2012
  Calling Method: Fri Jun 22 02:13:43 CDT 2012
  Calling Method: Fri Jun 22 02:13:43 CDT 2012
  Calling Method: Fri Jun 22 02:13:43 CDT 2012
    Result: My Name1: 6/22/2012 2:13:45 AM Background thread: 52 Main thread: 26
    Result: My Name3: 6/22/2012 2:13:47 AM Background thread: 38 Main thread: 49
    Result: My Name2: 6/22/2012 2:13:50 AM Background thread: 50 Main thread: 51

现在,没有锁​​定主线程只得到7从第一台服务器的方法调用到最后的响应已过秒钟=)

Now, only 7 seconds elapsed from the first server method call to the last response received without locking the main thread =)

如果我的理解是正确的,你需要传递一些参数的方法和数据集返回填写标签和文本框。

If my understanding is correct, you need to pass some parameters to the methods and return datasets to fill labels and textboxes.

要传递的参数的PageMethods,这是一个办法做到这一点:

To pass parameters to the PageMethods, this is a way to do it:

安装这些的NuGet包:

Install these Nuget Package:

  • https://nuget.org/packages/json2
  • https://nuget.org/packages/Newtonsoft.Json
  • https://nuget.org/packages/jQuery
  • https://nuget.org/packages/Rx-Main/1.0.11226

Command类。这个类将重新present你要发送到服务器的方法在后操作的参数

Command class. This class will represent the parameters you want to send to the server method in the post action

public class ProcessXmlFilesCommand
{
    public string XmlFilePath { get; set; }

    public ProcessXmlFilesCommand()
    {
    }
}

而不是返回的的DataSet ,我想它会更容易和更易于管理,以返回的IEnumerable 的东西像这样的:

Instead of returning a DataSet, I think it would be easier and more manageable to return an IEnumerable, something like this:

    [WebMethod]
    public static IEnumerable<MyResult> ProcessXmlFiles(ProcessXmlFilesCommand command)
    {
        List<MyResult> results = new List<MyResult>();
        var o = Observable.Start(() =>
        {
            // here do something useful, process your xml files for example
            // use the properties of the parameter command
            results.Add(new MyResult { SomethingInteresting = DateTime.Now.ToString(), FilePath = command.XmlFilePath + "Processed" });
            results.Add(new MyResult { SomethingInteresting = DateTime.Now.ToString(), FilePath = command.XmlFilePath + "Processed" });
            results.Add(new MyResult { SomethingInteresting = DateTime.Now.ToString(), FilePath = command.XmlFilePath + "Processed" });
            Thread.Sleep(2000);
        }, Scheduler.NewThread);
        o.First();
        return results.AsEnumerable();
    }

MyResult 类重presents要发送回用户的数据。

The MyResult class represents the data you want to send back to the user

public class MyResult
{
    public string SomethingInteresting { get; set; }
    public string FilePath { get; set; }
}

在您的ASPX页面

<script type="text/javascript" src="Scripts/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="Scripts/json2.min.js"></script>


    <script type="text/javascript">
        function processFiles() {
            var filePath = $("#filePath").val();
            var command = new processFilesCommand(filePath);
            var jsonCommand = JSON.stringify(command);

            $.ajax({
                cache: false,
                type: "POST",
                async: true,
                url: "CustomThreads.aspx/ProcessXmlFiles",
                data: "{'command':" + jsonCommand + "}",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (msg) {
                    onFileProcessedSuccess(msg);
                },
                error: function (exc) {
                    onFileProcessedError(exc);
                }
            });
        }
        function onFileProcessedSuccess(msg) {
            var response = msg.d;
            $.each(response, function (index, myResponse) {
                $("#<%:this.myLabel.ClientID %>").append(myResponse.SomethingInteresting + "<br/>");
            });
        }
        function onFileProcessedError(exc) {
            alert("Error: " + exc.responseText);
        }
        function processFilesCommand(filePath) {
            this.XmlFilePath = filePath;
        }
        $(document).ready(function () {
            $("#processFile").click(processFiles);
        });
    </script>

<input type="text" name="filePath" id="filePath" />
<input type="button" name="processFile" id="processFile" value="Process File" />

<br /><asp:Label ID="myLabel" runat="server" />

编辑2

这是一种简化的方式

Edit 2

This is a simplified way

<%@ Page EnableSessionState="False" Language="C#" AutoEventWireup="true" CodeBehind="CustomThreadsSimple.aspx.cs" Inherits="WebApplication1.CustomThreadsSimple" %>
....
<script type="text/javascript" src="Scripts/jquery-1.7.2.min.js"></script>
....
    <script type="text/javascript">
        function makeCall(url, data) {
            $("#<%:this.lblMessage.ClientID %>").append("<br/>Initializing call: " + new Date());
            $.ajax({
                url: url,
                type: "POST",
                dataType: "json",
                contentType: "application/json; charset=utf-8;",
                async: true,
                cache: false,
                data: "{name:'" + data + "'}",
                success: function (msg) {
                    $("#<%:this.lblMessage.ClientID %>").append("<br/>&nbsp;&nbsp;&nbsp;&nbsp;" + msg.d);
                },
                error: function (exc) {
                    alert(exc.responseText);
                }
            });
        }
        $(function () {
            $("#startProcess").click(function () {
                makeCall("CustomThreadsSimple.aspx/Execute1", $("#<%: this.txtData1.ClientID %>").val());
                makeCall("CustomThreadsSimple.aspx/Execute2", $("#<%: this.txtData2.ClientID %>").val());
                makeCall("CustomThreadsSimple.aspx/Execute3", $("#<%: this.txtData3.ClientID %>").val());
            });
        });
    </script>
    <asp:TextBox runat="server" ID="txtData1" />
    <asp:TextBox runat="server" ID="txtData2" />
    <asp:TextBox runat="server" ID="txtData3" />
    <input type="button" name="startProcess" id="startProcess" value="Start execution" />
    <asp:Label ID="lblMessage" runat="server" />

后面的 code

public partial class CustomThreadsSimple : System.Web.UI.Page
{
    [WebMethod]
    public static string Execute1(string name)
    {
        string res = string.Empty;
        Func<string, string> asyncMethod = x =>
        {
            Thread.Sleep(2000);
            return "Res1: " + x +" " + DateTime.Now.ToString() + " Background thread: " + Thread.CurrentThread.ManagedThreadId.ToString();
        };

        IAsyncResult asyncRes = asyncMethod.BeginInvoke(name, null, null);
        res = asyncMethod.EndInvoke(asyncRes);
        res += " Main thread: " + Thread.CurrentThread.ManagedThreadId.ToString();
        return res;
    }

    [WebMethod]
    public static string Execute2(string name)
    {
        string res = string.Empty;
        Func<string, string> asyncMethod = x =>
        {
            Thread.Sleep(7000);
            return "Res2: " + x + " " + DateTime.Now.ToString() + " Background thread: " + Thread.CurrentThread.ManagedThreadId.ToString();
        };

        IAsyncResult asyncRes = asyncMethod.BeginInvoke(name, null, null);
        res = asyncMethod.EndInvoke(asyncRes);
        res += " Main thread: " + Thread.CurrentThread.ManagedThreadId.ToString();
        return res;
    }

    [WebMethod]
    public static string Execute3(string name)
    {
        string res = string.Empty;
        Func<string, string> asyncMethod = x =>
        {
            Thread.Sleep(4000);
            return "Res3: " + x + " " + DateTime.Now.ToString() + " Background thread: " + Thread.CurrentThread.ManagedThreadId.ToString();
        };

        IAsyncResult asyncRes = asyncMethod.BeginInvoke(name, null, null);
        res = asyncMethod.EndInvoke(asyncRes);
        res += " Main thread: " + Thread.CurrentThread.ManagedThreadId.ToString();
        return res;
    }
}

输出

这篇关于如何显示异步结果哪一个是先在asp.netweb应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆