سؤال

I need to integrate a third party's Web API methods into a WCF service. The WCF Service will be called by another external party, and they expect the call and return to be synchronous.

I am able to get results from the API with the usual RestClient.ExecuteAsync.

I put together the following for synchronous calls:

public static List<Books> GetSyncBooks(int companyId)
{
    var response = GetSynchronousBooks(companyId);  
    var content = response.Result.Content;
    List<Books> result = new List<Books>();

    return Helpers.JSONSerialiser.Deserialize<BookList>(content);
}


async private static Task<IRestResponse> GetSynchronousBooks(int companyId)
{
    var request = BuildGETRequest("Book", companyId);
    var response = await RestSharpHelper.ExecuteSynchronousRequest(request);

    return response;
}

public static Task<IRestResponse> ExecuteSynchronousRequest(RestRequest request)
{
    var client = new RestClient(BaseUrl);
    client.AddHandler("application/json", new RestSharpJsonDotNetDeserializers());

    var tcs = new TaskCompletionSource<IRestResponse>(TaskCreationOptions.AttachedToParent);

    client.ExecuteAsync(request, (restResponse, asyncHandle) =>
    {                
        if (restResponse.ResponseStatus == ResponseStatus.Error)
            tcs.SetException(restResponse.ErrorException);
        else
            tcs.SetResult(restResponse);
    });
    return tcs.Task;
// BREAKPOINT here shows TASK value as
//  Id = 1, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}"
}

The problem, however, is that I never get a result using this. The response content is always null. What am I doing wrong?

EDIT: Thanks Stephen. I have seen your name on some of the questions here on this subject: your score seems to indicate you know your way around this. I have indeed implemented the wcf service calls as you indicated based on your answer at another question. Can I ask you a related follow-up question? How scalable are async WCF service calls like this example? Would it "just work" for multiple simultaneous calls in the range of 10 to 100 per second, ignoring the processing overhead downstream?

هل كانت مفيدة؟

المحلول

I assume that your WCF service is hosted in ASP.NET.

Your problem is here: response.Result. I explain this deadlock situation on my blog. In summary, await will capture the current "context" (in this case, an ASP.NET request context) and will use that to resume the async method. However, the ASP.NET request context only allows one thread at a time, so if the request thread is blocked (calling response.Result), then the async method can never continue and you get a deadlock.

The solution is to correct this misunderstanding:

The WCF Service will be called by another external party, and they expect the call and return to be synchronous.

Since you're dealing with a client/server scenario, you don't have to make it synchronous. The asynchrony of the client is completely independent from the asynchrony of the server.

So, just implement your WCF service asynchronously:

public static Task<List<Books>> GetBooksAsync(int companyId)
{
  var response = await GetBooksAsync(companyId);  
  var content = response.Content;
  List<Books> result = new List<Books>();

  return Helpers.JSONSerialiser.Deserialize<BookList>(content);
}

The client can still call it synchronously if they wish to.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top