我已将服务实现为WCF.我将服务引用添加到Web客户端时生成异步方法.
代码工作正常,但是当回调触发时屏幕会暂时锁定 – 我认为这是因为它们都是一个接一个地发生并且所有这些都在快速连续中重新绘制GridView.
我不希望这个故障发生 – 我希望AJAX实现能够部分更新GridView,因为结果通过回调从服务返回.
我可以使这看起来很好的唯一方法是在单独的客户端线程中启动异步调用,然后使用计时器将数据重新绘制到网格(通过回调在单独的线程中更新的相同数据).
我正在做这个迷你项目作为学习练习,然后我的目标是与MVC3一样来了解差异.
代码片段(没有单独的线程,导致回调期间屏幕渲染速度变慢):
//get list of connections from session ConnectionList myConns = Session[SESSION_ID] as ConnectionList; //pass into async service call GetAllStatusAsync(myConns); protected void GetAllStatusAsync(ConnectionList myConns) { Service1Client myClient = new WcfConnectionServiceRef.Service1Client(); myClient.AsyncWorkCompleted += new EventHandler<AsyncWorkCompletedEventArgs>(myClient_AsyncWorkCompleted); foreach (ConnectionDetail conn in myConns.ConnectionDetail) { //this call isnt blocking,conn wont be updated until later in the callback myClient.AsyncWorkAsync(conn); } } //callback method from async task void myClient_AsyncWorkCompleted(object sender,AsyncWorkCompletedEventArgs e) { ConnectionDetail connResult = e.Result; //get list of connections from session ConnectionList myConns = Session[SESSION_ID] as ConnectionList; //update our local store UpdateConnectionStore(connResult,myConns); //rebind grid BindConnectionDetailsToGrid(myConns); }
问题是 – 这可以在asp.net / AJAX中以更好的方式完成吗? (为了避免渲染锁定问题并在结果进入时让网格部分更新)我真的不想使用单独的客户端线程,如下面的代码片段:
// Perform processing of files async in another thread so rendering is not slowed down // this is a fire and forget approach so i will never get results back unless i poll for them in timer from the main thread ThreadPool.QueueUserWorkItem(delegate { //get list of connections from session ConnectionList myConns = Session[SESSION_ID] as ConnectionList; //pass into async service call GetAllStatusAsync(myConns); });
更新:
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="ASForm.aspx.cs" Inherits="Web_Asp_FBMonitor.ASForm" Async="true" EnableSessionState="True" %> <asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server"> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> ASP.NET Connection Test (Client in ASYNC,Server in ASYNC) </h2> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <p> <%--This update panel shows the time,updated every second--%> <asp:UpdatePanel ID="UpdatePanel2" runat="server"> <ContentTemplate> <h3> <asp:Label ID="LabelTime" runat="server" Text=""></asp:Label> </h3> <asp:Timer ID="Timer1" runat="server" Interval="1000" ontick="Timer1_Tick"> </asp:Timer> </ContentTemplate> </asp:UpdatePanel> </p> <p> <%--This update panel shows our results grid--%> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:GridView ID="GridView1" runat="server"> </asp:GridView> <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Default.aspx">Client Sync Page</asp:HyperLink> <br /> <asp:Button ID="ButtonUpdate" runat="server" Text="Update" onclick="ButtonUpdate_Click" /> </ContentTemplate> </asp:UpdatePanel> </p> </asp:Content>
更新2:
我正在寻找一个简洁的客户端JS示例.收到的选项很好,并且非常受欢迎,但客户端JS是我通过自己的经验缺乏并将为此奖励的奖励.
解决方法
ASP.NET WebForms试图使Web像Windows窗体一样.令人敬佩?取决于你问谁.
当您使用UpdatePanel时,ASP.NET将服务器端控件存储在ViewState中,对该ViewState进行必要的更改(在您的情况下,它根据Timer_Tick和ButtonUpdate_Click函数中的代码更新页面).然后,它使用此新数据刷新页面,从而导致您描述的屏幕锁定.
要解决这个问题,你必须使用真正的AJAX.很多人使用jQuery AJAX函数和以下选项之一来做到这一点:
> ASP.NET WebMethods
> WCF服务
>单独的ASP.NET页面
这里有很多关于通过jQuery挂起ASP.NET WebMethods的问题,还有一些关于加载ASP.NET页面的问题,但没有关于AJAX和WCF的问题.
如果您选择使用AJAX和jQuery,您的结果页面将如下所示:
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="ASForm.aspx.cs" Inherits="Web_Asp_FBMonitor.ASForm" Async="true" EnableSessionState="True" %> <asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server"> <!-- include jQuery library here --> <script language="javascript" type="text/javascript"> $(document).ready(function () { UpdateGrid(); // Separate AJAX call to another page,WCF service,or ASP.NET WebMethod for the Timer results }); function UpdateGrid() { $.ajax({ url: "GridViewResults.aspx",done: function (result) { $("#gridResults").html(result.d); } }); } </script> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> ASP.NET Connection Test (Client in ASYNC,Server in ASYNC) </h2> <p> <h3> <span id="timer"></span> </h3> </p> <p id="gridResults"> </p> <button id="ButtonUpdate" onclick="UpdateGrid();">Update</button> </asp:Content>
然后,在一个单独的页面上(我任意称之为上面的GridViewResults.aspx),您将拥有:
<asp:GridView ID="GridView1" runat="server"></asp:GridView> <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Default.aspx">Client Sync Page</asp:HyperLink> <br />