jar*_*ryd 7 .net c# rest wcf asynchronous
我们目前正在IIS中为我们的站点实现一个新的WCF REST服务,在许多页面上,我们可能会异步使用JQuery进行少量的AJAX调用.问题是好像WCF(在服务器端)同步执行.
在页面加载时,我们对3种不同的方法进行3次单独调用.使用日志记录,我可以看到它们都在大约5ms之内点击了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);
Run Code Online (Sandbox Code Playgroud)
以下是服务中某个实现的示例.
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;
}
Run Code Online (Sandbox Code Playgroud)
以下是我们在服务实现类上的属性.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
Run Code Online (Sandbox Code Playgroud)
任何人都可以提供一些见解,为什么这些是同步执行和我需要做什么,或者至少指出我需要做什么,让这些异步执行?
UPDATE
我接受了Matt的一些回答,并将我的逻辑移到了End函数调用,并关注他如何更紧密地将大文件上传到自托管WCF Rest服务.但是,我无法使用他的技术调用End方法.我也开始认为我会以错误的方式解决这个问题.因为查看日志,我的自定义身份验证服务正在每次服务调用之前执行,这发生在任何异步方法操作甚至触发之前.经过进一步调查后,我查看了进入IIS然后执行操作的每个请求的ThreadId.看来WCF只使用1个工作线程...句点.我一次向IIS发送了多少请求并不重要.例如,如果我发送3个请求,我可以看到它们都在不同的时间进入(彼此之间的毫秒数)并且都获得了自己的线程.但是,似乎WCF只是将它们全部排队并按顺序执行它们,因为它们都在同一个线程上执行,包括身份验证服务调用.
从你的例子来看,在我看来,你正在“开始”调用完成之前完成所有工作;这是我在学习异步模式时发现的一个常见错误。
\n\n虽然我不熟悉它在 WCF 中的应用,但异步模型更典型的是一个 Begin 方法,它启动一些新线程,其中的对象IAsyncResult
将由该新线程更新。要“完成”操作,当IsCompleted
设置为时true
,原始调用者应将原始IAsyncResult
对象传递回相应的 End 方法,该方法返回结果。一个简单的实现如下所示:
static Func<string> getUser;\n public static IAsyncResult BeginGetUser(AsyncCallback callback, object state)\n {\n getUser = () =>\n {\n Thread.Sleep(2000);\n return "finished";\n };\n return getUser.BeginInvoke(callback, state);\n }\n\n public static string EndGetUser(IAsyncResult asyncResult)\n {\n return getUser.EndInvoke(asyncResult);\n }\n
Run Code Online (Sandbox Code Playgroud)\n\n对它的调用可能如下所示:
\n\nvar result = BeginGetUser(null, null);\nstring value = EndGetUser(result);\n
Run Code Online (Sandbox Code Playgroud)\n\n当然,这是一个微不足道的案例:引用http://kennyw.com/work/indigo/258,“如果您\xe2\x80\x99t正在做\xe2\x80\x99s“本机异步”的事情,那么你不应该\xe2\x80\x99使用AsyncPattern=true”。
\n\n幸运的是,随着 C# 5.0 或 Microsoft 发布的 Async CTP,.Net 异步模式可能会成为过去。
\n 归档时间: |
|
查看次数: |
6650 次 |
最近记录: |