Асинхронные страницы нужно применять там, где может произойти задержка в выполнении запроса. Обычно это происходит при обращении к удаленному веб серверу или к удаленной базе данных. Время может колебаться от доли секунды до целой вечности и все это время основой поток ASP.NET будет занят, а сайт будет висеть.
начальная страница
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta charset="utf-8" /> <title></title> <style> h1 { text-align: center; } a { font-size: 22px; } </style> </head> <body> <form id="form1" runat="server"> <div> <h1>доступ к удаленной базе данных</h1> <br /> <br /> <a href="Page1.aspx" target="_blank">обычная страница</a> <br /> <br /> <a href="Page2.aspx" target="_blank">асинхронная страница</a> <br /> <br /> <a href="Page3.aspx" target="_blank">асинхронная страница с использование асинхронных задач класса PageAcyncTask</a> </div> </form> </body> </html>
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta charset="utf-8" /> <title></title> <style> h1 { text-align: center; } a { font-size: 22px; } </style> </head> <body> <form id="form1" runat="server"> <div> <h1>доступ к удаленной базе данных</h1> <br /> <br /> <a href="Page1.aspx" target="_blank">обычная страница</a> <br /> <br /> <a href="Page2.aspx" target="_blank">асинхронная страница</a> <br /> <br /> <a href="Page3.aspx" target="_blank">асинхронная страница с использование асинхронных задач класса PageAcyncTask</a> </div> </form> </body> </html>
обычная страница
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Page1.aspx.cs" Inherits="Page1" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta charset="utf-8" /> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" runat="server" Text=""></asp:Label> </div> </form> </body> </html>
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Page1.aspx.cs" Inherits="Page1" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta charset="utf-8" /> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" runat="server" Text=""></asp:Label> </div> </form> </body> </html>
Default.aspx.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; //добавить ссылку using MySql.Data.MySqlClient; using System.Configuration; public partial class Page1 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { string connectionString = ConfigurationManager.ConnectionStrings["abc"].ConnectionString; string sql = "SELECT id, name, amount, price FROM Book"; using(MySqlConnection connection = new MySqlConnection(connectionString)) { try { connection.Open(); MySqlCommand cmd = new MySqlCommand(sql, connection); MySqlDataReader reader = cmd.ExecuteReader(); while(reader.Read()) { Label1.Text += reader[0].ToString() + " " + reader[1].ToString() + " " + reader[2].ToString() + " " + reader[3].ToString() + "<br />"; } } catch { Label1.Text = "Error!"; } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; //добавить ссылку using MySql.Data.MySqlClient; using System.Configuration; public partial class Page1 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { string connectionString = ConfigurationManager.ConnectionStrings["abc"].ConnectionString; string sql = "SELECT id, name, amount, price FROM Book"; using(MySqlConnection connection = new MySqlConnection(connectionString)) { try { connection.Open(); MySqlCommand cmd = new MySqlCommand(sql, connection); MySqlDataReader reader = cmd.ExecuteReader(); while(reader.Read()) { Label1.Text += reader[0].ToString() + " " + reader[1].ToString() + " " + reader[2].ToString() + " " + reader[3].ToString() + "<br />"; } } catch { Label1.Text = "Error!"; } } } }
асинхронная страница
Для создания асинхронной страницы в директиве Page нужно указать атрибут Async="true"
Далее, нужно зарегистрировать методы начала и конца асинхронной операции в любом обработчике событий, которые следуют до обработчика события PreRender.
Далее, нужно зарегистрировать методы начала и конца асинхронной операции в любом обработчике событий, которые следуют до обработчика события PreRender.
Default.aspx
<%@ Page Language="C#" Async="true" AutoEventWireup="true" CodeFile="Page2.aspx.cs" Inherits="Page2" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" runat="server" Text=""></asp:Label> </div> </form> </body> </html>
<%@ Page Language="C#" Async="true" AutoEventWireup="true" CodeFile="Page2.aspx.cs" Inherits="Page2" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" runat="server" Text=""></asp:Label> </div> </form> </body> </html>
Default.aspx.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; //добавить ссылку using MySql.Data.MySqlClient; using System.Configuration; using System.Net; public partial class Page2 : System.Web.UI.Page { /*будет выполнять запрос к удаленному ресурсу*/ private WebRequest request = null; protected void Page_Load(object sender, EventArgs e) { /*регистрация методов начала и конца асинхронной операции*/ AddOnPreRenderCompleteAsync(new BeginEventHandler(BeginAsyncOperation), new EndEventHandler(EndAsyncOperation)); } /*начало асинхронной операции*/ //AsyncCallback cb - метод будет запускаться по звершению асинхронной задачи //object extraData - дополнительные данные состояния private IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object extraData) { //запрос к удаленному MySql серверу request = WebRequest.Create("http://ros6.jetget.ru"); //асинхронный запрос к удаленному ресурсу + //создается новый поток + //этот поток возвращается главному пулу ASP.NET return request.BeginGetResponse(cb, null); } /*конец асинхронной операции*/ private void EndAsyncOperation(IAsyncResult ar) { using(WebResponse responce = request.EndGetResponse(ar)) { string connectionString = ConfigurationManager.ConnectionStrings["abc"].ConnectionString; string sql = "SELECT id, name, amount, price FROM Book"; using(MySqlConnection connection = new MySqlConnection(connectionString)) { try { connection.Open(); MySqlCommand cmd = new MySqlCommand(sql, connection); MySqlDataReader reader = cmd.ExecuteReader(); while(reader.Read()) { Label1.Text += reader[0].ToString() + " " + reader[1].ToString() + " " + reader[2].ToString() + " " + reader[3].ToString() + "<br />"; } } catch { Label1.Text = "Error!"; } } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; //добавить ссылку using MySql.Data.MySqlClient; using System.Configuration; using System.Net; public partial class Page2 : System.Web.UI.Page { /*будет выполнять запрос к удаленному ресурсу*/ private WebRequest request = null; protected void Page_Load(object sender, EventArgs e) { /*регистрация методов начала и конца асинхронной операции*/ AddOnPreRenderCompleteAsync(new BeginEventHandler(BeginAsyncOperation), new EndEventHandler(EndAsyncOperation)); } /*начало асинхронной операции*/ //AsyncCallback cb - метод будет запускаться по звершению асинхронной задачи //object extraData - дополнительные данные состояния private IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object extraData) { //запрос к удаленному MySql серверу request = WebRequest.Create("http://ros6.jetget.ru"); //асинхронный запрос к удаленному ресурсу + //создается новый поток + //этот поток возвращается главному пулу ASP.NET return request.BeginGetResponse(cb, null); } /*конец асинхронной операции*/ private void EndAsyncOperation(IAsyncResult ar) { using(WebResponse responce = request.EndGetResponse(ar)) { string connectionString = ConfigurationManager.ConnectionStrings["abc"].ConnectionString; string sql = "SELECT id, name, amount, price FROM Book"; using(MySqlConnection connection = new MySqlConnection(connectionString)) { try { connection.Open(); MySqlCommand cmd = new MySqlCommand(sql, connection); MySqlDataReader reader = cmd.ExecuteReader(); while(reader.Read()) { Label1.Text += reader[0].ToString() + " " + reader[1].ToString() + " " + reader[2].ToString() + " " + reader[3].ToString() + "<br />"; } } catch { Label1.Text = "Error!"; } } } } }
асинхронная страница с использование асинхронных задач класса PageAcyncTask
Для создания асинхронной страницы в директиве Page нужно указать атрибут Async="true"
Для создания асинхронной страницы, которая использует класс PageAcyncTask нужно в файле Web.config установить данные настройки
Для создания асинхронной страницы, которая использует класс PageAcyncTask нужно в файле Web.config установить данные настройки
<!--обязательно установить данную настройку для Framework 4 и 4.5-->
<
appSettings
>
-
<
add
key
=
"aspnet:UseTaskFriendlySynchronizationContext"
value
=
"false"
/>
</
appSettings
>
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Page3.aspx.cs" Inherits="Page3" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta charset="utf-8" /> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" runat="server" Text=""></asp:Label> </div> </form> </body> </html>
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Page3.aspx.cs" Inherits="Page3" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta charset="utf-8" /> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" runat="server" Text=""></asp:Label> </div> </form> </body> </html>
Default.aspx.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; //добавить ссылку using MySql.Data.MySqlClient; using System.Configuration; using System.Net; public partial class Page3 : System.Web.UI.Page { /*будет выполнять запрос к удаленному ресурсу*/ private WebRequest request = null; protected void Page_Load(object sender, EventArgs e) { /*создаем экземпляр класса PageAsyncTask*/ //делегат OnBegin - начало асинхронной операции //делегат OnEnd - конец асинхронной операции //делегат OnTimeOut - метод возвратит сообщение, если лимит времени //ожидания (AsyncTimeout="40" по умолчанию) превышен //null - значение для аргумента extraData метода OnBegin PageAsyncTask task = new PageAsyncTask(OnBegin, OnEnd, OnTimeOut, null); /*регистрация*/ RegisterAsyncTask(task); } /*начало асинхронной операции*/ /*начало асинхронной операции*/ //AsyncCallback cb - метод будет запускаться по звершению асинхронной задачи //object extraData - дополнительные данные состояния private IAsyncResult OnBegin(object sender, EventArgs e, AsyncCallback cb, object extraData) { //запрос к удаленному MySql серверу request = WebRequest.Create("http://ros6.jetget.ru"); //асинхронный запрос к удаленному ресурсу + //создается новый поток + //этот поток возвращается главному пулу ASP.NET return request.BeginGetResponse(cb, null); } /*конец асинхронной операции*/ /*конец асинхронной операции*/ private void OnEnd(IAsyncResult ar) { using(WebResponse responce = request.EndGetResponse(ar)) { string connectionString = ConfigurationManager.ConnectionStrings["abc"].ConnectionString; string sql = "SELECT id, name, amount, price FROM Book"; using(MySqlConnection connection = new MySqlConnection(connectionString)) { try { connection.Open(); MySqlCommand cmd = new MySqlCommand(sql, connection); MySqlDataReader reader = cmd.ExecuteReader(); while(reader.Read()) { Label1.Text += reader[0].ToString() + " " + reader[1].ToString() + " " + reader[2].ToString() + " " + reader[3].ToString() + "<br />"; } } catch { Label1.Text = "Error!"; } } } } /*если лимит времени превышен*/ private void OnTimeOut(IAsyncResult ar) { Label1.Text = "Время ожидания gревышено!"; } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; //добавить ссылку using MySql.Data.MySqlClient; using System.Configuration; using System.Net; public partial class Page3 : System.Web.UI.Page { /*будет выполнять запрос к удаленному ресурсу*/ private WebRequest request = null; protected void Page_Load(object sender, EventArgs e) { /*создаем экземпляр класса PageAsyncTask*/ //делегат OnBegin - начало асинхронной операции //делегат OnEnd - конец асинхронной операции //делегат OnTimeOut - метод возвратит сообщение, если лимит времени //ожидания (AsyncTimeout="40" по умолчанию) превышен //null - значение для аргумента extraData метода OnBegin PageAsyncTask task = new PageAsyncTask(OnBegin, OnEnd, OnTimeOut, null); /*регистрация*/ RegisterAsyncTask(task); } /*начало асинхронной операции*/ /*начало асинхронной операции*/ //AsyncCallback cb - метод будет запускаться по звершению асинхронной задачи //object extraData - дополнительные данные состояния private IAsyncResult OnBegin(object sender, EventArgs e, AsyncCallback cb, object extraData) { //запрос к удаленному MySql серверу request = WebRequest.Create("http://ros6.jetget.ru"); //асинхронный запрос к удаленному ресурсу + //создается новый поток + //этот поток возвращается главному пулу ASP.NET return request.BeginGetResponse(cb, null); } /*конец асинхронной операции*/ /*конец асинхронной операции*/ private void OnEnd(IAsyncResult ar) { using(WebResponse responce = request.EndGetResponse(ar)) { string connectionString = ConfigurationManager.ConnectionStrings["abc"].ConnectionString; string sql = "SELECT id, name, amount, price FROM Book"; using(MySqlConnection connection = new MySqlConnection(connectionString)) { try { connection.Open(); MySqlCommand cmd = new MySqlCommand(sql, connection); MySqlDataReader reader = cmd.ExecuteReader(); while(reader.Read()) { Label1.Text += reader[0].ToString() + " " + reader[1].ToString() + " " + reader[2].ToString() + " " + reader[3].ToString() + "<br />"; } } catch { Label1.Text = "Error!"; } } } } /*если лимит времени превышен*/ private void OnTimeOut(IAsyncResult ar) { Label1.Text = "Время ожидания gревышено!"; } }
Web.config
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.5"> <assemblies> <add assembly="MySql.Data, Version=6.9.5.0, Culture=neutral, PublicKeyToken=C5687FC88969C44D"/> </assemblies> </compilation> <httpRuntime targetFramework="4.5"/> </system.web> <connectionStrings> <add name="abc" connectionString="Server=ros6.beget.ru;Database=zzz;User ID=tipliz;Password=12345"/> </connectionStrings> <!--обязательно установить данную настройку для Framework 4 и 4.5--> <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext" value="false" /> </appSettings> </configuration>
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.5"> <assemblies> <add assembly="MySql.Data, Version=6.9.5.0, Culture=neutral, PublicKeyToken=C5687FC88969C44D"/> </assemblies> </compilation> <httpRuntime targetFramework="4.5"/> </system.web> <connectionStrings> <add name="abc" connectionString="Server=ros6.beget.ru;Database=zzz;User ID=tipliz;Password=12345"/> </connectionStrings> <!--обязательно установить данную настройку для Framework 4 и 4.5--> <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext" value="false" /> </appSettings> </configuration>
нагрузочный тест
Обратите внимание на данные нагрузочного теста, обычная страница Page1практически в два раза загружается дольше, чем асинхронные страницы.