WCF REST不处理异步WCF、REST

2023-09-03 02:41:13 作者:习惯孤单

目前,我们正在实施一个新的WCF REST服务在IIS中为我们的网站,并就一些我们可以做一把AJAX调用的使用JQuery异步页。的问题是,它好像WCF(在服务器侧)执行同步

We are currently implementing a new WCF REST service in IIS for our site and on a number of pages we may be making a handful of AJAX calls using JQuery asynchronously. The problem is that it seems as though WCF (on the server side) is executing synchronously.

在页面加载,我们正在做3分别调用3种不同的方法。使用日志,我可以看到他们都在对方的命中为5ms Global.asax文件。从那里,记录显示的顺序,他们离开在Global.asax(不一定是在我们通过JavaScript的呼吁从页面的顺序)都执行。我希望每次调用接收自己的线程和单独返回。即使在安装调试时,我可以看到,它不会执行下一个方法,直到我通过目前的方法是在一步。

On page load we're making 3 separate calls to 3 different methods. Using logging, I can see them all hit the global.asax file within about 5ms of each other. From there, the logging shows everything executing in the order they exit the global.asax (not necessarily the order in which we made the calls from the page via javascript). I expected each call to receive their own thread and return individually. Even when attaching with the debugger I can see that it won't execute the next method until I step through the current method it's on.

下面是三个我'想'的方法的操作合同,我实现使用异步模式。

Here are the operation contracts for three of the methods I 'thought' I implemented to use the async model.

    [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);

下面是在该服务的实现之一的一个例子。

Here is an example of one of the implementations in the service.

    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;
    }

下面是属性,我们对服务实现类。

Here are the attributes we have on the service implementation class.

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]

任何人都可以请提供一些见解,为什么这些执行同步,什么我需要做的,或者至少是指向我什么,我需要做的方向,让这些异步执行?

Can anyone please provide some insight as to why these are executing synchronously and what I need to do, or at least point me in the direction of what I need to do, to get these to execute asynchronously?

更新

我花了一些马特的答案,并动了我的逻辑来结束函数调用,并随后对他怎么做这个博客帖子就多一点紧密Uploading大文件自托管WCF REST服务。但是,我无法得到最终的方法使用他的技术来调用。我也开始觉得我会对此错误的方式。因为看日志,我自定义的验证服务正在每个服务呼叫时,任何异步方法操作甚至起火前已发生之前执行。经过进一步调查,我看了一眼包含threadid的的每个请求进入IIS,然后执行该操作。看来,WCF仅使用1辅助线程...时期。不要紧,有多少请求我一次发送给IIS。举例来说,如果我送3的要求,我可以看到他们都来在不同的时间(在彼此的毫秒),并都得到自己的线程。但后来好像WCF只是排队它们并执行它们的顺序,因为它们都在同一个线程中执行,包括认证服务电话。

I took some of Matt's answer and moved my logic to the End function calls and followed this blog post on how he did it a bit more closely Uploading Large Files To Self Hosted WCF Rest Service. However, I couldn't get the End methods to call using his technique. I'm also starting to think I'm going about this the wrong way. Because looking at the logs, my custom authentication service is being executed before each service call, which happens before any async method operations even fire. After further investigation, I took a look at the ThreadId's of each request coming into IIS and then executing the operations. It appears that WCF is only using 1 worker thread... period. It doesn't matter how many requests I send at a time to IIS. For example, if I send 3 requests, I can see they all come in at different times (within milliseconds of each other) and all get their own thread. But then it seems WCF just queues them all and executes them in that order because they're all executed on the same thread, including the authentication service calls.

推荐答案

在我看来,从你的榜样,像你做的开始通话结束前的各项工作;这是一个常见的​​错误,我发现在学习异步模式。

It looks to me, from your example, like you're doing all the work before the "Begin" call finishes; that's a common mistake I found while learning the async pattern.

虽然我不熟悉它在WCF应用程序中,异步模式更是一种典型的开始方法启动了的IAsyncResult 对象的某些新线程被更新该新线程。以完整的动作,当 IsCompleted 设置为,原调用者有望通过原有的的IAsyncResult 对象返回给对应的End方法返回的结果。一个简单的实现如下所示:

Though I'm not familiar with its application in WCF, the Async model more typically is a Begin method that launches some new thread with a IAsyncResult object to be updated by that new thread. To "complete" the action, when IsCompleted is set to true, the original caller is expected to pass the original IAsyncResult object back to the corresponding End method which returns the result. A trivial implementation looks as follows:

    static Func<string> getUser;
    public static IAsyncResult BeginGetUser(AsyncCallback callback, object state)
    {
        getUser = () =>
            {
                Thread.Sleep(2000);
                return "finished";
            };
        return getUser.BeginInvoke(callback, state);
    }

    public static string EndGetUser(IAsyncResult asyncResult)
    {
        return getUser.EndInvoke(asyncResult);
    }

在调用它可能是这样的:

The calls to it might look like:

var result = BeginGetUser(null, null);
string value = EndGetUser(result);

当然,这是一个简单的情况:引用 http://kennyw.com/work/indigo / 258 ,如果你没有做的事情是本机异步,那么你不应该使用AsyncPattern =真。

Of course, this is a trivial case: to quote http://kennyw.com/work/indigo/258, "If you aren’t doing something that’s "natively async", then you shouldn’t be using AsyncPattern=true".

幸运的是,C#5.0或异步CTP,微软发布时,.NET异步模式可能会成为过去的事情了。

Fortunately, with C# 5.0 or the Async CTP that Microsoft released, the .Net async pattern may become a thing of the past.