【问题标题】:To invoke a method asynchronously by using BeginInvoke and save the result in Session state使用 BeginInvoke 异步调用方法并将结果保存在 Session 状态
【发布时间】:2012-07-14 22:18:20
【问题描述】:

我有这个使用 begininvoke 异步调用方法的示例代码,我在 web 表单上的按钮单击事件上执行它。

点击按钮后,用户被重定向到另一个页面,用户在此等待结果。

AuthorizePayment 方法需要很长时间才能运行并返回一个 int 代码。我想将该 int 值存储在会话或 cookie 中的某处(但不显示)当我访问 Session 以添加该代码时,它会引发空异常。如何将此结果保存在会话或 cookie 中?

有什么想法吗?

    public class CreditCardAuthorizationManager
{
  // Delegate, defines signature of method(s) you want to execute asynchronously
  public delegate int AuthorizeDelegate(string creditcardNumber, 
                                        DateTime expiryDate, 
                                        double amount);

  // Method to initiate the asynchronous operation
  public void StartAuthorize()
  {
      AuthorizeDelegate ad = new AuthorizeDelegate(AuthorizePayment);
      IAsyncResult ar = ad.BeginInvoke(creditcardNumber, 
                                       expiryDate, 
                                       amount,                  
                                       new AsyncCallback(AuthorizationComplete), 
                                       null);
  }

  // Method to perform a time-consuming operation (this method executes 
  // asynchronously on a thread from the thread pool)
  private int AuthorizePayment(string creditcardNumber, 
                               DateTime expiryDate, 
                               double amount)
  {
    int authorizationCode = 0;

    // Open connection to Credit Card Authorization Service ...
    // Authorize Credit Card (assigning the result to authorizationCode) ...
    // Close connection to Credit Card Authorization Service ...
    return authorizationCode;
  }

  // Method to handle completion of the asynchronous operation
  public void AuthorizationComplete(IAsyncResult ar)
  {
    // See "Managing Asynchronous Completion with the EndInvoke Method"
    // later in this chapter.
  }
}

【问题讨论】:

  • 需要更多信息才能了解您无法访问会话的原因。这些是aspx 页面吗?目标页面如何“等待”响应,您是否从脚本中轮询某些内容?我一般同意@usr,您应该使用ajax 而不是从aspx 代码隐藏启动线程(如果这是您正在做的事情)但是这里有很多关于架构的缺失信息,以了解可能出现的问题。
  • @jamietre 这是真实场景。真实场景是在登录我的应用程序时从第三方供应商处获取令牌。我不希望我的用户等待第三方供应商返回令牌(以防供应商系统运行缓慢)。拥有这个令牌是件好事,但不是强制性的。如果我们有令牌,它将在整个应用程序中使用,而不是在一页中。
  • @jamietre 只有当我将 HttpContext.Current 传递给委托时,我才能访问会话。我只是担心,因为这个委托可以超过页面请求的生命周期,以及分配给该页面请求的 HttpContext 对象的有效生命周期。
  • 我想我明白了 - 你是说你将 HttpContext 传递给你的后台线程并且当你以后尝试从该线程访问它时它不再可用(例如 null)?从未尝试过,但很有意义。使用另一种机制在后台线程和活动会话之间共享此信息,例如尝试传递当前HttpContextCache 属性-缓存是全局的,并且未绑定到特定的上下文,因此我认为对它的引用不应随上下文而死。如果这不起作用,那么直接进入数据库?

标签: c# asp.net session asynchronous begininvoke


【解决方案1】:

您无法跨 HTTP 请求可靠地执行工作,因为 ASP.NET 工作进程可能会在任意时刻中止。付款可能已由提供商执行,但您的网站可能认为尚未执行(并且付款已丢失)。我当然不想将我的信用卡数据输入这样的系统。

更好的方法是在 AJAX 请求上运行支付并同步执行授权代码。

【讨论】:

  • 嗯,这只是一个例子。我的真实场景不是信用卡系统。所以,从你的意思来看,现在我可以在用户会话中临时保存该授权代码(或称其为其他名称)?
  • 真实情况是在登录我的应用程序时从第三方供应商处获取令牌。我不希望我的用户等待第三方供应商返回令牌(以防供应商系统运行缓慢)。拥有这个令牌是件好事,但不是强制性的。如果我们有令牌,它将在整个应用程序中使用,而不是在一页中。这有意义吗?
  • 好的,这使它更可行。尽管中止工人的问题仍然存在:异步网络 IO 可能被中止。但是,有一种方法可以使工作进程保持活动状态(研究 RegisterObject)。顺便说一句,从我的角度来看,你在做什么是有道理的。会话:是的,您可以将其存储在那里。我的问题是网络 IO 仍在运行的时间跨度(并且可能会被随机终止)。
  • 明白。将被随机杀死的部分放在一边。如何将其存储在会话中?我无法访问会话,它在运行时引发错误。如何获取会话以在 AuthorizationPayment 方法中添加此供应商密钥?
  • @BrokenLink,这是另一个问题。 "如何从线程池线程访问会话"
【解决方案2】:

您可以使用 async 关键字创建方法并返回任务,而不是创建开始调用和使用委托。

在您的原始方法中,您可以将异步方法称为

 Task<int> authorizationValue = await yourAsyncMethodCall(creditcardNumber, expirydate, amount)

  session["authorisation"] = authorizationValue;

如果您需要更具体的示例,请告诉我(我的 VS.net 坏了,所以我必须在这里输入 :()

【讨论】:

    猜你喜欢
    • 2019-12-28
    • 2016-05-14
    • 2015-04-26
    • 1970-01-01
    • 2019-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-01
    相关资源
    最近更新 更多