如何显示异步结果在asp.netweb应用程序中哪一个是第一个?
我必须在三个类文件中发送三个异步请求,三个请求的响应时间不同,第一个是2秒,第二个是7秒,第三个是4秒,现在我必须在浏览器中显示第一个响应,在2秒后显示第三个响应,最后显示第二个响应,但现在我的结果在完成三个回复后一次显示所有回复,请给我任何建议,这是非常紧急的,请 我的代码是如何显示异步结果在asp.netweb应用程序中哪一个是第一个?,asp.net,asynchronous,Asp.net,Asynchronous,我必须在三个类文件中发送三个异步请求,三个请求的响应时间不同,第一个是2秒,第二个是7秒,第三个是4秒,现在我必须在浏览器中显示第一个响应,在2秒后显示第三个响应,最后显示第二个响应,但现在我的结果在完成三个回复后一次显示所有回复,请给我任何建议,这是非常紧急的,请 我的代码是 public delegate string AsyncMethodCaller(string name); public delegate string AsyncMethodCallertest(st
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我认为问题的根源在于理解ASP.Net请求会发生什么 每个页面都有其生命周期,其中包括一系列事件。每个请求都由来自当前应用程序AppDomain的工作线程处理。在页面管道完成之前,不会将响应发送给用户 关于线程: 可以在
machine.config
中配置同时可用线程的数量。要理解的关键点是,这些线程数是固定的,这意味着当达到最大并发线程数时,后续请求将被放入队列中,可放入队列的请求数仅受服务器内存的限制
当工作线程调用耗时较长的操作时,您将阻塞该线程,直到操作完成,这意味着,如果有多个并发用户,则可能会阻塞所有可用线程,从而强制将新请求放入队列,在最坏的情况下,会导致503错误-服务不可用
防止这种情况的方法是在后台线程中调用此类方法与您的代码类似,但行为与您预期的不同。在本例中,您的代码正在等待线程结束,以便完成页面请求,这就是您同时(在请求结束时)收到结果的原因
有关异步执行asp.net页面的详细信息
现在,为了获得所需的结果:
(这是一个完整的工作示例,在这个示例中,我使用它在一个新线程中运行耗时较长的方法,如果您愿意,您可以将其更改为使用另一个框架,我更喜欢使用Rx,因为我觉得使用API更舒服)
使用分页方法
代码隐藏
ASPX
如您所见,代码未优化,主线程被锁定,我们设置的最大秒数为7秒,但在本例中,从调用服务器代码(02:11:17)到接收到最后一个响应(2:11:30)已过13秒。这是因为ASP.Net默认情况下会锁定当前的会话
对象,并锁定主线程。由于本例中未使用会话,因此可以如下配置页面:
<%@ Page EnableSessionState="False"
[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();
}
现在,从第一个服务器方法调用到最后一个接收到的响应只花了7秒,而没有锁定主线程=)
编辑1
如果我的理解是正确的,您需要将一些参数传递给方法并返回数据集以填充标签和文本框
要将参数传递给PageMethods,以下是一种方法:
安装以下Nuget软件包:
public class ProcessXmlFilesCommand
{
public string XmlFilePath { get; set; }
public ProcessXmlFilesCommand()
{
}
}
与返回数据集
不同,我认为返回IEnumerable
会更容易、更易于管理,类似这样:
<%@ Page EnableSessionState="False"
[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();
}
在您的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" />
函数processFiles(){
var filePath=$(“#filePath”).val();
var命令=新的ProcessFileCommand(文件路径);
var jsonCommand=JSON.stringify(命令);
$.ajax({
cache:false,
类型:“POST”,
async:true,
url:“CustomThreads.aspx/ProcessXmlFiles”,
数据:“{'command':”+jsonCommand+“}”,
contentType:“应用程序/json;字符集=utf-8”,
数据类型:“json”,
成功:功能(msg){
onFileProcessedSuccess(msg);
},
错误:函数(exc){
onFileProcessedError(exc);
}
});
}
函数onFileProcessedSuccess(msg){
var响应=msg.d;
$.each(响应、函数(索引、myResponse){
$(“#”)追加(myResponse.SomethingInterest+“
”;
});
}
函数onFileProcessedError(exc){
警报(“错误:+exc.responseText”);
}
函数ProcessFileCommand(文件路径){
this.XmlFilePath=filePath;
}
$(文档).ready(函数(){
$(“#进程文件”)。单击(进程文件);
});
编辑2
这是一种简化的方法
<%@ 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/> " + 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" />
....
....
函数makeCall(url、数据){
$(“#”)追加(
初始化调用:“+new Date());
$.ajax({
url:url,
类型:“POST”,
数据类型:“json”,
contentType:“应用程序/json;字符集=utf-8;”,
async:true,
cache:false,
数据:“{name:'”+data+“}”,
成功:功能(msg){
$(“#”)追加(“
”+msg.d);
},
错误:函数(exc){
警报(exc.responseText);
}
});
}
$(函数(){
$(“#启动进程”)。单击(函数(){
makeCall(“CustomThreadsSimple.aspx/Execute1”,$(“#”).val();
makeCall(“CustomThreadsSimp
public class MyResult
{
public string SomethingInteresting { get; set; }
public string FilePath { get; set; }
}
<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" />
<%@ 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/> " + 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" />
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;
}
}