【发布时间】:2011-05-11 04:09:51
【问题描述】:
我们目前正在为我们的站点在 IIS 中实现新的 WCF REST 服务,并且在许多页面上,我们可能会使用 JQuery 异步进行少量 AJAX 调用。问题是 WCF(在服务器端)似乎是同步执行的。
在页面加载时,我们对 3 种不同的方法进行了 3 次单独调用。使用日志记录,我可以看到它们都在大约 5 毫秒内击中了 global.asax 文件。从那里,日志显示所有执行的顺序,它们退出 global.asax(不一定是我们通过 javascript 从页面进行调用的顺序)。我希望每个调用都能接收到自己的线程并单独返回。即使使用调试器附加,我也可以看到它不会执行下一个方法,直到我逐步执行它所在的当前方法。
以下是我“认为”为使用异步模型而实施的三种方法的操作协定。
[OperationContract(AsyncPattern = true)]
[WebInvoke(
Method = "POST"
, UriTemplate = "/ListUserPreferences"
, BodyStyle = WebMessageBodyStyle.Wrapped
, ResponseFormat = WebMessageFormat.Json
, RequestFormat = WebMessageFormat.Json
)]
IAsyncResult BeginListUserPreferences(AsyncCallback callback, object state);
Result<List<Data.EnumerationItem<UserPreferenceType>>> EndListUserPreferences(IAsyncResult asyncResult);
[OperationContract(Name = "GetUserSecure", AsyncPattern = true)]
[WebInvoke(
Method = "POST"
, UriTemplate = "/GetUser"
, BodyStyle = WebMessageBodyStyle.Wrapped
, ResponseFormat = WebMessageFormat.Json
, RequestFormat = WebMessageFormat.Json
)]
IAsyncResult BeginGetUser(AsyncCallback callback, object state);
Result<Data.User> EndGetUser(IAsyncResult asyncResult);
[OperationContract(AsyncPattern = true)]
[WebInvoke(
Method = "POST"
, UriTemplate = "/ListWithAttributes"
, BodyStyle = WebMessageBodyStyle.Wrapped
, ResponseFormat = WebMessageFormat.Json
, RequestFormat = WebMessageFormat.Json
)]
IAsyncResult BeginListWithAttributes(int index, int pageSize, AsyncCallback callback, object state);
Result<PagedCollection<Data.Attribute>> EndListWithAttributes(IAsyncResult asyncResult);
这是服务中的一种实现示例。
public IAsyncResult BeginGetUser(AsyncCallback callback, object state)
{
var asyncResult = new CompletedAsyncResult<Result<Data.User>>(state);
asyncResult.Result = new Result<Data.User>();
asyncResult.Result.Value.UserId = Guid.Empty;
asyncResult.Result.Value.DisplayName = "asdfasd";
asyncResult.IsCompleted = true;
callback(asyncResult);
return asyncResult;
}
public Result<Data.User> EndGetUser(IAsyncResult asyncResult)
{
return ((CompletedAsyncResult<Result<Data.User>>)asyncResult).Result;
}
这是我们在服务实现类上的属性。
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
谁能提供一些关于为什么这些同步执行以及我需要做什么的见解,或者至少指出我需要做什么的方向,以使这些异步执行?
更新
我接受了 Matt 的一些回答,并将我的逻辑转移到了 End 函数调用,并关注了这篇博文,了解他是如何更紧密地做到这一点的 Uploading Large Files To Self Hosted WCF Rest Service。但是,我无法使用他的技术调用 End 方法。我也开始认为我正在以错误的方式解决这个问题。因为查看日志,我的自定义身份验证服务在每次服务调用之前执行,这发生在任何异步方法操作甚至触发之前。经过进一步调查,我查看了进入 IIS 并执行操作的每个请求的 ThreadId。看来 WCF 只使用 1 个工作线程...期间。我一次向 IIS 发送多少请求并不重要。例如,如果我发送 3 个请求,我可以看到它们都在不同的时间(彼此相隔几毫秒)进入并且都有自己的线程。但是看起来 WCF 只是将它们全部排队并按顺序执行它们,因为它们都在同一个线程上执行,包括身份验证服务调用。
【问题讨论】:
-
您似乎没有在该方法中执行任何异步工作。运行同步操作并将其结果放入 IAsyncResult 不会使方法异步(除非该代码不代表您的实现)。
-
我确定我只是没有完全理解它是如何工作的。我给出的例子是我试图让它发挥作用。我正在/正在关注有关如何设置异步调用的博客文章。我同意运行同步操作并且做我所做的不会使它异步,我想我不知道为什么它们首先要同步运行。你能详细说明一下吗?如果需要,我可以提供更多信息。
标签: c# .net wcf rest asynchronous