gpt4 book ai didi

c# - ASP 中的异步 Web 服务。网络MVC

转载 作者:太空狗 更新时间:2023-10-30 01:18:28 25 4
gpt4 key购买 nike

我正在编写一个 ASP.NET MVC 5 应用程序,其中使用 Web 服务来获取/处理一些数据。

应用程序的数据流如下:MVC Action -> Service B -> ExtSvc,它是 Web 服务的异步包装器

这里有一些例子:

public class ExtSvc
{
//Convert Event based async pattern to task based async pattern:

private Task<Response> ProcessExtRequestAsync(Request request)
{
TaskCompletionSource<Response> taskCompletionSource =
AsyncServiceClientHelpers.CreateSource<Response>(request);
ProcessRequestCompletedEventHandler handler = null;
handler =
(sender, e) =>
AsyncServiceClientHelpers.TransferCompletion(
taskCompletionSource,
e,
() => e.Result,
() => this.Service.ProcessRequestCompleted -= handler);
this.Service.ProcessRequestCompleted += handler;
try
{
this.Service.ProcessRequestAsync(request, taskCompletionSource);
}
catch (Exception)
{
this.Service.ProcessRequestCompleted -= handler;
taskCompletionSource.TrySetCanceled();
throw;
}

return taskCompletionSource.Task;
}

//Usage:

public async Task<Response> UpdateRequest(some arguments)
{
//Validate arguments and create a Request object

var response = await this.ProcessExtRequestAsync(request)
.ConfigureAwait(false);

return response;
}
}

B 类是以同步方式使用 ExtSvc 的类

public class B
{
public ExtSvc service {get; set;}

public Response Update(arguments)
{
//some logic
var result = this.ExtSvc.UpdateRequest(arguments).Result;
//some logic
return result
}
}

最后是 MVC 操作(也是同步)

public ActionResult GetResponse(int id)
{
//some logic
B.Update(id);
//some logic
return View(...);
}

描述的流程抛出错误

A first chance exception of type 'System.InvalidOperationException' occurred in System.Web.dll

Additional information: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it.

在 ExtSvc 的以下行中:this.Service.ProcessRequestAsync(request, taskCompletionSource); ProcessRequestAsync是一个无效的方法所以它对应于:

This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing

我知道将 GetResponse MVC 操作转换为异步操作(通过使用 async/await)并将实际使用 ExtSvc 的 B 类转换为异步操作可以解决问题。

但我的问题是:

如果我无法更改 B 类的签名(因为它实现了一个接口(interface))以返回 Task<Response>而不是 Response这基本上意味着我不能对其使用 async/await 那么如何解决这个问题?

最佳答案

ProcessRequestAsyncvoid但它不是 async void .它看起来像一个 EBAP API . EBAP 组件 generally use AsyncOperationManager / AsyncOperation ,这又是do use SynchronizationContext to notify the underlying platform of the asynchronous operation (最后一个链接是我在 SynchronizationContext 上的 MSDN 文章)。

你看到的异常是因为 ASP.NET 看到通知(异步操作开始)并说“哇,伙计。你是一个同步处理程序!没有异步你!”

毫无疑问,最好的方法是将所有应该异步的方法设为异步。这意味着 B.Update应该是 B.UpdateAsync .好的,所以有一个接口(interface) IB.Update - 只需将界面更改为 IB.UpdateAsync也。然后你一路异步,代码就干净了。

否则,您将不得不考虑黑客攻击。你可以使用 Task.Run正如@neleus 所建议的那样——这是一种避免 ASP.NET SynchronizationContext 的方法所以它不会“看到”异步操作开始 - 但请注意“环境上下文”,例如 HttpContext.Current并且页面文化丢失了。或者,您可以(暂时)安装 new SynchronizationContext()到请求线程 - 这也避免了 ASP.NET SynchronizationContext同时保持在同一个线程上 - 但一些 ASP.NET 调用假设存在 ASP.NET SynchronizationContext并且会失败。

您可以尝试另一种技巧;它可能有用,但我从来没有做过。只需让您的处理程序返回 Task<ActionResult>并使用 Task.FromResult返回 View :return Task.FromResult<ActionResult>(View(...));此 hack 将告诉 ASP.NET 您的处理程序是异步的(即使它不是)。

当然,所有这些 hack 都有一个主要的缺点,即您正在执行同步异步(this.ExtSvc.UpdateRequest(arguments).Result),这意味着您将在每个请求的持续时间内使用一个额外的不必要的线程(或 < em>两个 线程,如果你使用 Task.Run hack)。因此,您首先会失去使用异步处理程序的所有好处 - 即可伸缩性。

关于c# - ASP 中的异步 Web 服务。网络MVC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27374085/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com