天道酬勤,学无止境

ASP.NET Webforms with async/await

问题

我基于 .Net 4.6 的 Webforms 应用程序必须非常广泛地使用 async/await 功能。 因为我对这个 async/await 主题很陌生,所以我阅读了很多类似这样或这样的最佳实践。 但是我仍然有一些问题,我没有找到任何明确的信息。

  1. 关于 Page-Lifecycle-Events:我知道,例如对于 Page_Load-Event,最好的做法是避免异步 void 方法并注册这样的方法:

     protected void Page_Load(object sender, EventArgs e) { PageAsyncTask pageAsyncTask = new PageAsyncTask(SomeAsyncMethod); Page.RegisterAsyncTask(pageAsyncTask); //Method to invoke the registered async-methods immedietly and not after the PreRender-Event Page.ExecuteRegisteredAsyncTasks(); }

    我的问题是我想在注册后立即调用异步方法,而不是在 OnPreRender 事件之后。 这应该通过调用 ExecuteRegisteredAsyncTasks() 方法来实现。 但在我的情况下,这没有效果,并且在 PreRender 事件之后仍然调用异步方法。 但为什么?

  2. 关于 Control-Events:以我在上面的代码示例中提到的相同方式注册 async-methods 是否更好,或者我可以使用 async-void 签名,例如:

     protected async void OnClick(object sender, EventArgs e) { await SomeAsyncMethod(); }

    我找到了这两个示例,但没有明确的信息是更好的解决方案以及原因。

  3. 关于 Context 和 ConfigureAwait,最好的做法是使用await SomeAsyncMethod.ConfigureAwait(false)以获得更好的性能和上下文不重要的地方,而不是在上下文中使用它,例如在操作 GUI 元素时。 但就我而言,如果我在点击事件中调用await SomeAsyncMethod.ConfigureAwait(false)似乎没有什么区别。 我仍然可以毫无问题地操作我的 GUI 元素。 我使用的示例是这样的:

     private async void button1_Click(object sender, EventArgs e) { button1.Enabled = false; try { await SomeAsyncMethod().ConfigureAwait(false); } finally { //Manipulating still works even it's another context button1.Enabled = true; } }

所以我想知道为什么 GUI 元素的操作仍然有效,如果我真的应该在上下文不重要的每个异步方法上使用 ConfigureAwait(false),这非常乏味。 我想知道这是否与 Telerik 用于我的 Web 应用程序的 Ajax-Functionality 的使用有关。 但这只是一个假设。

回答1

ASP.NET WebForms 有它自己的异步执行引擎。 请参阅文档。

在任何情况下,您通常希望(或需要)返回到事件处理程序等方法的当前同步上下文,因此您不应该在button1_Click中调用ConfigureAwait(false) ,而应该在SomeAsyncMethod中调用它。

回答2

我对 Asp.net 4.5 网络表单的简单方法:

1)用这个属性声明aspx页面

<%@ Page ..... Async="true" ValidateRequest="false" EnableEventValidation="false" %>

2) 在代码中创建这个 void 方法:

void MyAsyncMethod( ... list parameters )
{
  //Insert this on end method code
  var objThread = Session["MyAsyncMethod"] as Thread;
  if (objThread != null) objThread.Abort();
}

3)调用方法MyAsyncMethod:

var objThread = new Thread(
              () => MyAsyncMethod(parameters..)) {IsBackground = true};
objThread.Start();
Session["MyAsyncMethod"] = objThread;

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • ASP.NET Webforms with async/await
    My Webforms application which is based on .Net 4.6 has to use the async/await-functionality quite extensively. Because I'm quite new to this async/await topic I read quite a lot of best practices like this or this. But I still have some questions for which I haven't found any clear informations. Regarding Page-Lifecycle-Events: I know that e.g. for the Page_Load-Event it's best practice to avoid async void-methods and register such methods like this: protected void Page_Load(object sender, EventArgs e) { PageAsyncTask pageAsyncTask = new PageAsyncTask(SomeAsyncMethod); Page.RegisterAsyncTask
  • DbConnection.Open() 有效,但 dbConnection.OpenAsync() 无效(DbConnection.Open() works but dbConnection.OpenAsync() doesn't)
    问题 这是困难的一个。 使用完全相同的查询字符串,完全相同的以下代码: using (var db = new SqlConnection(queryString)) { await db.OpenAsync(); var results = await db.ExecuteSomethingAsync...; db.Close(); { 从 Windows 应用程序运行时将起作用。 然而,当从 IIS Express 或 IIS 7 运行时,它会永远停留在await OpenAsync() 。如果我用db.Open()替换该行,它虽然可以工作。 有什么建议么? 回答1 正如其他人所提到的,首先确保您的层次结构中没有Wait或Result调用。 一系列async方法在依赖于框架的入口点结束。 在 UI/WebForms 应用程序中,这通常是一个async void事件处理程序。 在 WebAPI/MVC 应用程序中,这通常是一个async操作。 检查 ASP.NET 的另外两件事是: 确保您的目标平台是 .NET 4.5。 确保您已将UseTaskFriendlySynchronizationContext设置为true 。 如果您需要在多个平台上的共享库中支持async ,您可能会发现Microsoft.Bcl.Async NuGet 库很有帮助。 回答2 await在 ASP
  • EntityFramework(6)和异步(waitingForActivation)?(EntityFramework (6) and async ( waitingForActivation)?)
    问题
  • Mono .Net 支持异步等待?(Mono .Net support for async await?)
    问题 我想知道 Linux 上的 Mono 是否支持使用 async await 关键字功能编写自托管 WebApi 项目。 我发现了这个:在兼容性页面上的 Mono 网站上: 然后有一些文字说有限的 ASP.NET 4.5 异步堆栈。 所以......我很困惑...... Mono 4.5 支持或不支持什么异步/等待方面? 回答1 Mono 很久以前就克隆了 ASP.NET 2 管道,以支持基于“System.Web”程序集的经典 ASP.NET WebForms。 由于微软的初始设计,该模型是同步模型。 但是,后来微软在 .NET 4/4.5 时间范围内向管道 (System.Web) 添加了许多异步功能,这是 Mono 尚未完全克隆的新设计。 这大概就是这一段背后的意思。 我不认为 Mono 应该继续使用“System.Web”,因为甚至微软在不久前也放弃了它,转而支持 OWIN,现在是 ASP.NET 5/DNX。 更新: 请立即切换到 ASP.NET Core,因为它是跨平台 Web 应用程序领域中最好的。
  • How to use async/await to achieve asynchronous page in asp.net webform?
    We can now use the async/await key words in ASP.NET MVC 4. public async Task<ActionResult> TestAsync() { WebClient client = new WebClient(); return Content(await client.DownloadStringTaskAsync("http://www.google.com")); } But how to use it in ASP.NET WebForms?
  • 运行异步任务时如何立即更新 UI(How to update UI immediately when running an async task)
    问题 我有一个 Asp.Net 4.5 webforms 应用程序,其中包含我尝试使用 async await 运行的报告。 这是我正在使用的代码示例: protected async void btnReport_Click(object sender, EventArgs e) { lblStatus.Text = "Working!"; await LongRunningTask(); } private async Task LongRunningTask() { await Task.Delay(5000); lblStatus.Text = "Done!"; } 我读过的所有内容似乎都表明第一种方法应该立即完成并更新标签,但事实并非如此。 在 LongRunningTask 完成之前,该方法仍会绑定 UI。 如果我从 btnReport_Click 中删除 async 和 await,UI 会立即更新,但是当 LongRunningTask 完成时,我会收到一个没有特定信息的未处理异常。 请让我知道我在这里不明白的地方。 回答1 我有一个类似的问题要求。 无需 ajax 或 JavaScript 并使用 4.5 框架解决。 以下是对可能阅读本文的人的一些建议: • 确保您的 page.aspx 声明具有以下内容: <%@ Page Title="" Async=
  • 无法理解异步和等待(Trouble understanding async and await)
    问题 我一直在尝试理解 C# 中的 async/await 和 Task,但尽管观看了 youtube 视频、阅读了文档并遵循了复数课程,但一直失败。 我希望有人能够帮助回答这些稍微抽象的问题,以帮助我解决问题。 1. 为什么他们说 async/await 启用了“异步”方法,而其本身的 async 关键字什么也不做,而 await 关键字添加了一个暂停点? 不是添加暂停点强制方法同步操作,即在继续之前完成由 await 标记的任务。 2.显然,除了事件处理程序外,您不应该使用 async void,那么您通常如何调用 async 方法? 似乎为了使用 await 关键字调用异步方法,调用它的方法/类本身需要标记为异步。 我见过的所有示例都使用事件处理程序“启动”了一个异步 void 方法。 您将如何“逃避”这种对 async/await 的包装以运行该方法? 3. public async Task SaveScreenshot(string filename, IWebDriver driver) { var screenshot = driver.TakeScreenshot(); await Task.Run(() => { Thread.Sleep(2000); screenshot.SaveAsFile(filename, ScreenshotImageFormat
  • How to update UI immediately when running an async task
    I have an Asp.Net 4.5 webforms application with a report which I'm trying to run using async await. Here is an example of the code I'm using: protected async void btnReport_Click(object sender, EventArgs e) { lblStatus.Text = "Working!"; await LongRunningTask(); } private async Task LongRunningTask() { await Task.Delay(5000); lblStatus.Text = "Done!"; } Everything I've read seems to suggest that the first method should complete immediately and update the label but this is not the case. The method still ties up the UI until LongRunningTask completes. If I remove async and await from btnReport
  • 在 MVC Action 中启动和忘记异步任务(Starting and Forgetting an Async task in MVC Action)
    问题 我有一个标准的非异步操作,例如: [HttpPost] public JsonResult StartGeneratePdf(int id) { PdfGenerator.Current.GenerateAsync(id); return Json(null); } 我知道这个 PDF 生成可能需要很长时间,所以我只是开始任务并返回,而不关心异步操作的结果。 在默认的 ASP.Net MVC 4 应用程序中,这给了我一个很好的例外: System.InvalidOperationException: 此时无法启动异步操作。 异步操作只能在异步处理程序或模块内或在页面生命周期中的某些事件期间启动。 如果在执行 Page 时发生此异常,请确保将 Page 标记为 <%@ Page Async="true" %>。 这与我的场景无关。 查看它,我可以将标志设置为 false 以防止出现此异常: <appSettings> <!-- Allows throwaway async operations from MVC Controller actions --> <add key="aspnet:AllowAsyncDuringSyncStages" value="true" /> </appSettings> https://stackoverflow.com/a/15230973
  • 在Razor视图中使用await(Use of await in Razor views)
    问题 是否可以在Razor .cshtml视图中await任务? 默认情况下,它抱怨只能在带有async标记的方法中使用,所以我想知道是否某个隐藏开关启用了它? 回答1 在ASP.NET Core 2.1中,可以在Razor视图中使用await 。 参见https://docs.microsoft.com/zh-cn/aspnet/core/mvc/views/partial?view=aspnetcore-2.1 例子: @await Html.PartialAsync("../Account/_LoginPartial.cshtml") 回答2 不,这是不可能的,无论如何您都不需要这样做。 剃刀视图应包含标记和最多一些帮助程序调用。 async / await属于您的后端逻辑。 回答3 我一直想要这样的事情-如果我们的许多页面不必编写一堆查询,那么我们编写的许多页面可能会被Jr Dev扔到一起。 而且,无论如何每次都是相同的基本查询样板-当他们的大部分工作都是为了获得内容时,为什么他们必须为每个Controller编写它们呢? 我使用C#,所以不必处理内存管理,为什么HTML编码器必须处理查询详细信息? 您可以使用一种技巧来将数据异步加载到视图中。 首先,您定义一个类,该类表示所需的数据。 然后,在每个View的顶部实例化该类。 回到Controller中
  • 长时间运行ASP.NET时IIS请求超时(IIS Request Timeout on long ASP.NET operation)
    问题 运行长时间的操作时,我正在从IIS请求超时。 在后台,我的ASP.NET应用程序正在处理数据,但是正在处理的记录数很大,因此该操作要花费很长时间。 但是,我认为IIS使会话超时。 IIS或ASP.NET会话有问题吗? 提前致谢 回答1 如果要延长ASP.NET脚本执行所允许的时间,请增加Server.ScriptTimeout值。 .NET 1.x的默认值为90秒,.NET 2.0及更高版本的默认值为110秒。 例如: // Increase script timeout for current page to five minutes Server.ScriptTimeout = 300; 也可以在web.config文件的httpRuntime配置元素中配置此值: <!-- Increase script timeout to five minutes --> <httpRuntime executionTimeout="300" ... other configuration attributes ... /> 请注意根据MSDN文档: “仅当编译元素中的debug属性为False时,此超时才适用。因此,如果debug属性为True,则不必将此属性设置为较大的值,以避免在调试时关闭应用程序。 ” 如果您已经完成此操作,但是发现会话即将到期,则增加ASP.NET
  • async await Task null reference exception
    I am getting NullReferenceExceptions on a webforms project I'm maintaining. The catch is that there is no stacktrace for this exception because none of my code causes the exception. Exception details copied to the clipboard offers zero assistance: System.NullReferenceException was unhandled Message: An unhandled exception of type 'System.NullReferenceException' occurred in mscorlib.dll Additional information: Object reference not set to an instance of an object. When I view the non-user code stacktrace, I see the following (all in mscorlib): The error occurs randomly and inconsistently, either
  • 异步等待任务空引用异常(async await Task null reference exception)
    问题 我在维护的 webforms 项目中收到 NullReferenceExceptions。 问题是这个异常没有堆栈跟踪,因为我的代码都没有导致异常。 复制到剪贴板的异常详细信息提供零帮助: System.NullReferenceException was unhandled Message: An unhandled exception of type 'System.NullReferenceException' occurred in mscorlib.dll Additional information: Object reference not set to an instance of an object. 当我查看非用户代码堆栈跟踪时,我看到以下内容(均在 mscorlib 中): 该错误通过加载页面或回发随机且不一致地发生。 在我添加System.Net.Http.HttpClient以从其他站点上公开的 REST 服务中提取数据后,问题就开始了。 请注意, HttpClient 仅包含用于发送/接收数据的异步方法。 基于内部堆栈跟踪,我高度怀疑 Task<>/async/await 是罪魁祸首。 为了帮助进行故障排除,让我重申一下,我正在使用 .NET 4.6 编译的 WebForms 站点中运行它(如果您要告诉我我的问题是我需要升级到 MVC
  • 在ASP.NET事件处理程序中使用异步/等待是否安全?(Is it safe to use async/await in ASP.NET event handlers?)
    问题 遇到此问题时,我正在ASP.NET中进行一些编码: protected async void someButtonClickHandler(...) { if(await blah) doSomething(); else doSomethingElse(); } 问了这个问题之后,我对async / await工作方式有了更好的了解。 但是然后让我吃惊的是,以上述方式使用async / await是否安全? 我的意思是,在调用await blah之后,调用者将继续执行。 这意味着它可能在await blah完成之前将响应呈现回客户端。 这是正确的吗? 如果是这种情况, doSomething() / doSomethingElse()会发生什么。 他们会被处决吗? 如果执行了这些命令,用户是否会看到其更改的效果? 就我而言,这些方法会更改一些显示给用户的数据,但我也想知道一般情况下会发生什么。 回答1 是的,它很安全,但不建议这样做。 推荐的方法是通过RegisterAsyncTask。 但是,ASP.NET(Web窗体)将正确处理async void事件处理程序。 当处理程序await s时,不会将响应呈现给客户端。 await仅产生于ASP.NET运行时,而不产生给客户端。 ASP.NET运行时知道事件处理程序尚未完成,因此它知道不发送响应。 事件处理程序完成后,ASP
  • ASP.NET WebApi 后台异步/等待(async/await in background in ASP.NET WebApi)
    问题 假设我有以下异步方法需要相当长的时间才能完成其工作: void async Task LongWork() { await LONGWORK() // ... long work } 现在,在 web api 中,我想在后台运行该工作(即,我想在启动 LongWork() 之后但在完成之前返回 Http 请求: 我可以想到三种方法来实现这一目标: 1) public async Task<string> WebApi() { ... // do another work await Task.Factory.StartNew(() => LongWork()); return "ok"; } 2) public async Task<string> WebApi() { ... // do another work await Task.Factory.StartNew(async () => await LongWork()); return "ok"; } 3) public async Task<string> WebApi() { ... // do another work Task.Factory.StartNew(async () => await LongWork()); return "ok"; } Q1:方法#1 和#2 有什么区别? Q2:在 ASP
  • How async / await can help in ASP.Net application?
    问题 使用 MVC 控制器的 async / await in action 方法可以扩展 Web 应用程序,因为在 await 时,Asp.Net 线程池的请求线程被释放,以便它可以为该工作进程处理 IIS 队列中的其他请求。 这意味着如果我们将工作进程的队列长度限制为 10,并向异步操作发送 50 - 100 个请求,则 IIS 不应返回 HTTP 503 错误,因为总会有一个来自 Asp.Net 线程池的空闲线程来服务器传入的请求。 我有一个 WebApi 进行如下计算: public class ValuesController : ApiController { public int GetSum(int x, int y, int timeDelay = 1) { Thread.Sleep(timeDelay*1000); int result = x + y; return result; } } 此操作方法仅延迟给定的秒数,然后将总和结果返回给调用代码。 非常基本的 web api,只是为了模仿长时间运行的代码。 接下来是等待结果的 MVC 异步操作: public class ThreadStarvationController : Controller { public async Task<ActionResult>
  • 通过ASP.NET Web API有效地使用异步/等待(Effectively use async/await with ASP.NET Web API)
    问题 我试图在我的Web API项目中使用ASP.NET的async/await功能。 我不太确定这是否会对我的Web API服务的性能产生任何影响。 请从我的应用程序下面找到工作流程和示例代码。 工作流程: UI应用程序→Web API端点(控制器)→Web API服务层中的调用方法→调用另一个外部Web服务。 (这里有数据库交互等) 控制器: public async Task<IHttpActionResult> GetCountries() { var allCountrys = await CountryDataService.ReturnAllCountries(); if (allCountrys.Success) { return Ok(allCountrys.Domain); } return InternalServerError(); } 服务层: public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries() { var response = _service.Process<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries"); return Task.FromResult(response); }
  • 在 ASP.Net 应用程序中调用异步 API(Calling Asynchronous API in ASP.Net Application)
    问题 我对 ASP.Net 和异步编码有点陌生,所以请耐心等待。 我已经用 C# 为我想在 ASP.Net 应用程序中使用的 Web API 编写了一个异步包装器。 这是 C# API 包装器中的函数之一: public async Task<string> getProducts() { Products products = new Products(); products.data = new List<Item>(); string URL = client.BaseAddress + "/catalog/products"; string additionalQuery = "include=images"; HttpResponseMessage response = await client.GetAsync(URL + "?" + additionalQuery); if (response.IsSuccessStatusCode) { Products p = await response.Content.ReadAsAsync<Products>(); products.data.AddRange(p.data); while (response.IsSuccessStatusCode && p.meta.pagination.links.next !=
  • 什么时候应该在ASP.NET MVC中使用异步控制器?(When should I use Async Controllers in ASP.NET MVC?)
    问题 我在ASP.NET MVC中使用异步操作时有些担心。 什么时候可以改善我的应用程序的性能,什么时候不可以? 在ASP.NET MVC的任何地方使用异步操作是否很好? 关于等待方法:当我要查询数据库时(通过EF / NHibernate /其他ORM),我应该使用async / await关键字吗? 一个单一的操作方法可以使用await关键字异步查询数据库多少次? 回答1 当一个动作必须执行几个独立的长时间运行的操作时,异步动作方法很有用。 AsyncController类的典型用法是长时间运行的Web服务调用。 我的数据库调用应该是异步的吗? IIS线程池通常可以比数据库服务器处理更多的同时阻止请求。 如果数据库是瓶颈,异步调用将不会加快数据库响应速度。 如果没有限制机制,则通过使用异步调用有效地将更多工作分配给不堪重负的数据库服务器,只会将更多的负担转移到数据库上。 如果您的数据库是瓶颈,那么异步调用将不是魔术。 您应该看一下1和2参考 源自@PanagiotisKanavos评论: 而且,异步并不意味着并行。 异步执行使宝贵的线程池线程免于阻塞外部资源,而没有任何复杂性或性能成本。 这意味着同一台IIS机器可以处理更多的并发请求,而不是运行得更快。 您还应该考虑到阻塞调用始于占用大量CPU的Spinwait。 在压力时期,阻止呼叫将导致延迟升级和应用程序池回收。
  • ASP.NET 4.5 异步等待和 Response.Redirect(ASP.NET 4.5 async-await and Response.Redirect)
    问题 使用async - await时,有什么方法可以从Page_Load (或任何其他 ASP.NET 事件)重定向? 当然Redirect会抛出ThreadAbortException但即使我用try catch它 - catch它最终会出现一个错误页面。 如果我调用Response("url", false)它不会崩溃但我需要停止页面的执行(呈现页面等)所以这不是解决方案。 正如我注意到这两种方法的行为不同: 这以 ThreadAbortException 结束(我假设任务同步结束): protected async void Page_Load() { await Task.Run(() => { }); Response.Redirect("http://www.google.com/"); } 这个在 Response.Redirect 之后继续: protected async void Page_Load() { await Task.Delay(1000); Response.Redirect("http://www.google.com/"); } 我必须等待响应,但我正在试验,即使我删除了await关键字(因此任务在后台运行并且方法继续),它最终还是一样。 唯一有帮助的是删除async关键字 - 我认为async只启用await仅此而已?! 回答1 好的