Веб-формы asp.net - async ждут исключения - PullRequest
0 голосов
/ 19 июня 2019

All

Я использую веб-формы asp.net, asp.net 4.7.2. ПРИМЕЧАНИЕ. Страница помечена как

Async="true"

Я создал пользовательский элемент управления, в котором есть событие (в моем примере: событие ProcessOrder). Когда пользовательский элемент управления пытается вызвать событие

this.ProcessOrder?.Invoke(this, args);

Я сразу получаю это исключение:

System.InvalidOperationException: 'Асинхронная операция не может быть запущена в это время. Асинхронные операции могут быть запущены только внутри асинхронного обработчика или модуля или во время определенных событий в жизненном цикле страницы. Если это исключение произошло во время выполнения страницы, убедитесь, что страница помечена как <% @ Page Async = "true"%>. Это исключение может также указывать на попытку вызова метода «async void», который обычно не поддерживается при обработке запроса ASP.NET. Вместо этого асинхронный метод должен возвращать задачу, а вызывающая сторона должна ожидать ее. '

Подпись метода обработчика событий на странице:

protected async void PaymentOptions_ProcessOrder(object sender, PaymentOptions.ProcessOrderEventArgs e)

и выполняет эту строку:

await _SubmitOrderAsync(e.PaymentToken, e.PaymentTokenDescriptor);

который в свою очередь выполняет мой метод отправки асинхронной электронной почты

await this.CheckoutServices.TrySendOrderConfirmationEmailAsync(receipt);

Как я уже говорил, я пометил страницу как асинхронную и следовал протоколу для асинхронных методов, не зная, в чем проблема.

UPDATE:

Я внес небольшое изменение в код, удалил ключевое слово async из обработчика событий PaymentOptions_ProcessOrder и поэтому больше не жду метода _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);

Должен ли я использовать другую строку?

1 Ответ

0 голосов
/ 20 июня 2019

Согласно документации , единственный способ выполнить асинхронный код - это использовать асинхронные задачи страницы.

Вот рабочий пример:

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;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...