ServiceStack “new” api and async await

2019-05-01 12:05发布

问题:

ServiceStack version 3

I'm quite familiar with https://github.com/ServiceStack/ServiceStack/wiki/New-API and on this page it specifically says "All these APIs have async equivalents which you can use instead, when you need to."

Is it possible to use async await with ServiceStack's new api?

What would the server and client code look like with async await?

[Route("/reqstars")]
public class AllReqstars : IReturn<List<Reqstar>> { }

public class ReqstarsService : Service
{
    public List<Reqstar> Any(AllReqstars request) 
    {
        return Db.Select<Reqstar>();
    }
}

Client

var client = new JsonServiceClient(BaseUri);
List<Reqstar> response = client.Get(new AllReqstars());

Would some please convert these synchronous examples to asynchronous?

回答1:

The "async" methods mentioned in the documentation do not return Task so they can't be used with async/await as they are. They actually require callbacks to call on success or failure.

E.g. the signature for GetAsync is :

public virtual void GetAsync<TResponse>(string relativeOrAbsoluteUrl, 
    Action<TResponse> onSuccess, 
    Action<TResponse, Exception> onError)

This is the APM-style of asynchronous functions and can be converted to Task-based functions using a TaskCompletionSource, eg:

    public static Task<TResponse> GetTask<TResponse>(this JsonServiceClient client, string url)
    {
        var tcs = new TaskCompletionSource<TResponse>();

        client.GetAsync<TResponse>(url,
            response=>tcs.SetResult(response),
            (response,exc)=>tcs.SetException(exc)
            );

        return tcs.Task;
    }

You can call the extension method like this:

var result = await client.GetTask<SomeClass>("someurl");

Unfortunatelly, I had to name the method GetTask for obvious reasons, even though the convention is to append Async to methods that return Task.



回答2:

With ServiceStack 4, GetAsync now returns a Task, so can can simply use await as expected:

var client = new JsonServiceClient(BaseUri);
var response = await client.GetAsync(new AllReqstars());

Documentation here: https://github.com/ServiceStack/ServiceStack/wiki/C%23-client#using-the-new-api

Note: From what I can tell ServiceStack v4 has many breaking changes from v3.x, and has moved away from BSD licensing with usage limits for their free tier: https://servicestack.net/pricing, so upgrading to 4 may not be an option.