全部
我正在使用asp.net Web表单,asp.net 4.7.2。 注意:该页面被标记为
Async="true"
我创建了一个具有事件的用户控件(在我的示例中:ProcessOrder事件)。当用户控件尝试引发事件
this.ProcessOrder?.Invoke(this, args);
我立即收到此异常:
System.InvalidOperationException:'此时无法启动异步操作。异步操作只能在异步处理程序或模块内或在页面生命周期中的某些事件期间启动。如果在执行页面时发生此异常,请确保该页面被标记为<%@ Page Async =“ true”%>。此异常也可能表示尝试调用“异步无效”方法,ASP.NET请求处理通常不支持该方法。相反,异步方法应返回一个Task,而调用者应等待它。'
页面上的事件处理程序方法签名为:
protected async void PaymentOptions_ProcessOrder(object sender, PaymentOptions.ProcessOrderEventArgs e)
并执行以下行:
await _SubmitOrderAsync(e.PaymentToken, e.PaymentTokenDescriptor);
依次执行我的发送异步电子邮件方法
await this.CheckoutServices.TrySendOrderConfirmationEmailAsync(receipt);
就像我提到的那样,我标记了“异步”页面,并且确实遵循异步方法的协议,不确定是什么问题。
更新:
我对代码进行了一些更改,从PaymentOptions_ProcessOrder事件处理程序中删除了async关键字,因此,我不再等待_SubmitOrderAync()方法了(这很好,因为之后没有代码)。但是,在SubmitOrderAsync()方法中
private async void _SubmitOrderAsync(string paymentToken, string paymentTokenDescriptor)
我正在等待TrySendOrderConfirmationEmailAsync()
await this.CheckoutServices.TrySendOrderConfirmationEmailAsync(receipt);
现在,当我运行此代码时,在调用_SubmitOrderAsync()时,它会爆炸,并且出现相同的异常(基本上,用async关键字修饰的第一个方法都会出错)。现在不确定,我可以等待的所有方法都返回一个任务,但_SubmitOrderAsync()除外,我不再等待了。
更新2
好的,要进一步解决此问题,我在同一页面上创建了一个虚拟按钮,并为其创建了一个异步onclick事件处理程序
protected async void btnGO_Click(object sender, EventArgs e)
我将要尝试在其中运行的异步方法TrySendOrderConfirmationEmailAsync()放入其中,并且可以正常运行! 调用按钮单击事件处理程序与我的用户控件的事件处理程序之间有什么区别????同样,我使用这一行在用户控件中调用我的事件处理程序:
this.ProcessOrder?.Invoke(this, args);
我应该使用其他行吗?
答案 0 :(得分:0)
根据documentation,执行异步代码的唯一方法是使用页面异步任务。
这是一个可行的示例:
Default.aspx:
<%@ Page Language="C#" AutoEventWireup="True" CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" Async="True" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<p>
<asp:Label ID="IsPostBackLabel" runat="server" Text=""></asp:Label>
</p>
<p>
<asp:Button ID="Button1" runat="server" Text="Button 1" OnClick="Button1_Click" /><asp:Label ID="IsButton1Label" runat="server" Text="Clicked!"></asp:Label>
</p>
<p>
<asp:Button ID="Button2" runat="server" Text="Button 2" OnClick="Button2_Click" /><asp:Label ID="IsButton2Label" runat="server" Text="Clicked!"></asp:Label>
</p>
<p>
<asp:Button ID="Button3" runat="server" Text="Button 3" OnClick="Button3_Click" /><asp:Label ID="IsButton3Label" runat="server" Text="Clicked!"></asp:Label>
</p>
</div>
</form>
</body>
</html>
Default.aspx.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
private bool isPostBack;
private int buttonclicked;
protected override void OnLoad(EventArgs e)
{
this.RegisterAsyncTask(
new PageAsyncTask(
this.IsPostBack
? new Func<Task>(OnPostBackAsync)
: new Func<Task>(OnNotPostBackAsync)));
}
protected override void OnPreRenderComplete(EventArgs e)
{
base.OnPreRender(e);
this.IsPostBackLabel.Text = this.isPostBack
? "This was a post back!"
: "This was not a post back!";
this.IsButton1Label.Visible = this.buttonclicked == 1;
this.IsButton2Label.Visible = this.buttonclicked == 2;
this.IsButton3Label.Visible = this.buttonclicked == 3;
}
protected void Button1_Click(object sender, EventArgs e)
{
this.RegisterAsyncTask(
new PageAsyncTask(
() => OnButtonClickedAsync(1)));
}
protected void Button2_Click(object sender, EventArgs e)
{
this.RegisterAsyncTask(
new PageAsyncTask(
() => OnButtonClickedAsync(2)));
}
protected void Button3_Click(object sender, EventArgs e)
{
this.RegisterAsyncTask(
new PageAsyncTask(
() => OnButtonClickedAsync(3)));
}
private async Task OnPostBackAsync()
{
await Task.Delay(1).ConfigureAwait(false);
this.isPostBack = true;
}
private async Task OnNotPostBackAsync()
{
await Task.Delay(1).ConfigureAwait(false);
this.isPostBack = false;
}
private async Task OnButtonClickedAsync(int button)
{
await Task.Delay(1).ConfigureAwait(false);
this.buttonclicked = button;
}
}
}