【问题标题】:Async in WebForms EventsWebForms 事件中的异步
【发布时间】:2014-07-16 15:15:26
【问题描述】:

我正在尝试在 WebForms 应用程序中使用新的 ASP.NET Identity 2.0 身份验证系统,但在允许用户保存数据源之前验证用户时遇到了问题。

问题源于从数据源的OnUpdating 事件调用IIdentityValidator.ValidateAsync。该标记在功能上与默认的动态数据模板相同(除了添加了Async="true"),在后面的代码中进行了一些自定义。基本上,我为请求手动设置了MetaTable(因为这个页面是我的一个动态数据路由的替代品,但我想保留脚手架属性的好处)并且我添加了DetailsDataSource_Updating 事件.虽然下面的代码示例成功地将用户保存到我们的数据库中,但在返回客户端之前通常会抛出以下错误:

“异步模块或处理程序已完成,而异步操作仍处于挂起状态。”

我花了相当多的时间试图让它工作,但还没有找到不锁定页面或抛出上述错误的解决方案。我担心我完全误解了 WebForms 中的 async/await,或者更糟的是,async/await 仅适用于 MVC 之外的数据库查询/绑定。

public partial class Edit : System.Web.UI.Page
{
    protected UserManager manager;
    protected CustomMetaTable table;

    protected void Page_Init(object sender, EventArgs e)
    {
        manager = UserManager.GetManager(Context.GetOwinContext());
        table = Global.DefaultModel.GetTable(typeof(User)) as CustomMetaTable;
        DynamicDataRouteHandler.SetRequestMetaTable(Context, table);
        FormView1.SetMetaTable(table);
        DetailsDataSource.EntityTypeFilter = table.EntityType.Name;
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        Title = table.EntityName;
        DetailsDataSource.Include = table.ForeignKeyColumnsNames;
    }

    protected void FormView1_ItemCommand(object sender, FormViewCommandEventArgs e)
    {
        if (e.CommandName == DataControlCommands.CancelCommandName)
        {
            Response.Redirect(table.ListActionPath);
        }
    }

    protected void FormView1_ItemUpdated(object sender, FormViewUpdatedEventArgs e)
    {
        if (e.Exception == null || e.ExceptionHandled)
        {
            Response.Redirect(table.ListActionPath);
        }
    }

    protected async void DetailsDataSource_Updating(object sender, Microsoft.AspNet.EntityDataSource.EntityDataSourceChangingEventArgs e)
    {
        IdentityResult result = await manager.UserValidator.ValidateAsync(e.Entity as User);
        if (!result.Succeeded)
        {
            e.Cancel = true;
        }
    }

【问题讨论】:

  • 这篇文章可能有用:hanselman.com/blog/…
  • @AntP 所以我基本上仅限于Page.RegisterAsyncTask 进行任何异步处理?
  • 通常当 EventHandler 调用该方法并在该方法中设置 e.Cancel = true 时,它​​会取消进一步的事件,但是当使用异步该方法时,EventHandler 调用者不会等待并继续事件,然后随时调用 e.Cancel = true。
  • 使用 WebForms,您必须考虑页面生命周期。您通过所有事件来收集页面的新状态。您处理该状态以获取系统的新状态(这是唯一可以异步的部分)。您生成新页面。
  • @PauloMorgado 基本上,Page.RegisterAsyncTask 是 WebForms 唯一可行的异步方法的问题是肯定的。

标签: c# asp.net webforms async-await


【解决方案1】:

在编写具有同步验证方法的新 UserValidator 的过程中,I found a class in the Identity assembly 用于 UserManagerRoleManager 的所有同步包装器中。我将这个类复制到我的项目中,它允许我同步使用异步方法,只有少数异常(通过在其他地方引用结果之前将结果分配给变量似乎可以避免主要异常)。

internal static class AsyncHelper
{
    private static readonly TaskFactory _myTaskFactory = new TaskFactory(
        CancellationToken.None,
        TaskCreationOptions.None, 
        TaskContinuationOptions.None, 
        TaskScheduler.Default);

    public static TResult RunSync<TResult>(Func<Task<TResult>> func)
    {
        return _myTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult();
    }

    public static void RunSync(Func<Task> func)
    {
        _myTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult();
    }
}

用法:

AsyncHelper.RunSync(() => manager.UserValidator.ValidateAsync(e.Entity as User));

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-09
  • 1970-01-01
  • 2017-08-29
  • 1970-01-01
  • 2018-06-11
  • 1970-01-01
相关资源
最近更新 更多