1

I have a couple of services running, A and B (both are web api) and an http client. This is the sequence of events I want accomplish asynchronously:

  1. Client calls A and passes an object O as parameter,
  2. A begins async process (P1) to do something with O,
  3. While P1 is running A sends asynchronous message to B [P2] (which may take a while) for B to do something with it. Essentially A is now the client of B

[ this is the important part ]

  1. As soon as P1 is finished doing its work I want A to send OK response back to the calling client,
  2. I don't want to make the client wait until B sends its own response to A before A can respond to the client with an OK,
  3. As far as the client is concerned A does only P1 and that's it, does not care about communication between A and B, it only cares about the results of P1
  4. A should handle whatever response B may send on its own time at its own pace
  5. Both P1 and P2 are async methods, which I have already defined and working

6-9 are only for clarification purposes, but how do I accomplish 5?

I'm working with MS stack, VS2013, C#5

Here is pseudo code I'm trying to implement:

 // this is the clinent and where it all begins
class Class1
{
    static void Main()
    {
        using (var client = new HttpClient())
        {
            var o = new SomeObject();
            var response = client.PostAsJsonAsync(api, o);
            Console.Write(response.Status);
        }
    }
}

// this one gets called from the client above
class ServiceA
{
    public async Task<IHttpActionResult> Post([FormBody] SomeObject someObject)
    {
        // this one I want to wait for
        var processed = await ProcessSomeObjectA(SomeObject some);

        // now, how do I call SendToService so that this POST
        // will not wait for completion
        SendToService(someObject);

        return processed.Result;

    }

    private async Task<bool> ProcessSomeObjectA(SomeObject some)
    {
        // whatever it does it returns Task<bool>
        return true;
    }

    private async Task<IHttpActionResult> SendToService(SomeObject someObject)
    {
        using (var client = new HttpClient())
        {
            var o = new SomeObject();
            var response = await client.PostAsJsonAsync(api, o);
            return response.StatusCode == HttpStatusCode.OK;
        }
    }

}

class ServiceB
{
    // this gets called from ServiceA
    public async Task<IHttpActionResult> Post([FormBody] SomeObject someObject)
    {
        return (await ProcessSomeObjectB(someObject))) ? Ok() : BadResponse();
    }

    private async Task<bool> ProcessSomeObjectB(SomeObject some)
    {
        // whatever it does it returns Task<bool>
        return true;
    }
}
user981375
  • 639
  • 1
  • 5
  • 15
  • can you provide some example code? Would it be as easy as simply not awaiting on P2 within P1? I am assuming that P1 can return safely without needing anything that P2 does. EDIT: I just re-read #7... don't think it's that simple. – Borophyll Dec 01 '15 at 17:53
  • You state you already have async code so it is not clear what your actual question is. What do you have so far? Please provide some code to act as a reference and then explain what/where it is you are stuck. – Igor Dec 01 '15 at 18:08
  • @Borophyll That's correct P1 does not care about what P2 does or return. Only the client cares about P1. Whatever P2 returns should be handled by ServiceA. We want to simulate long running process (P2) about which client does not care about but it's called from ServiceA (which in turn is called byt the client) – user981375 Dec 02 '15 at 04:27
  • @Igor I included the pseudo code above. It's not so much about detailed implementation of these async methods but how to call them so that there is no wait for results (in ServiceA) – user981375 Dec 02 '15 at 04:30
  • I think you want to get your hands on one of these: https://github.com/StephenCleary/AsyncEx/wiki/AsyncContext – ta.speot.is Dec 02 '15 at 05:31

3 Answers3

1

Try the following code in service "A":

public async Task<HttpResponseMessage> ServiceAAction()
{
    try
    {
        var client = new HttpClient();
        client.GetAsync("http://URLtoWebApi/ServiceB").ContinueWith(HandleResponse);

        // any code here will execute immediately because the above line is not awaited

        // return response to the client indicating service A is 'done'
        return Request.CreateResponse(HttpStatusCode.OK);

    }
    catch
    {
        throw new HttpResponseException(HttpStatusCode.InternalServerError);
    }
}

private async void HandleResponse(Task<HttpResponseMessage> response)
{
    try
    {
        // await the response from service B
        var result = await response;

        // do work

        // dont attempt to return anything, service A has already returned a response to the client
    }
    catch (Exception e)
    {
        throw;
    }
}

I have played with this a little bit. My test client (that consumes "A") receives a response message immediately. The method HandleResponse() is hit after the second api ("B") has finished its work. This setup cannot return a second message back to the client of "A", which is what I believe you are after anyways.

Borophyll
  • 1,099
  • 2
  • 15
  • 24
0

I guess what you want is for the B method to be called in a "fire and forget" way:

    public Task TaskA(object o)
    {
        //Do stuff

        //Fire and Forget: call Task B, 
        //create a new task, dont await 
        //but forget about it by moving to the next statement
        TaskB(); 

        //return;
    }
    public  Task TaskB()
    {
        //...
    }

    public async Task Client()
    {
        var obj = "data";

        //this will await only for TaskA
        await TaskA(obj);
    }
Golois Mouelet
  • 307
  • 2
  • 10
  • The thing is that TaskB is a web api end point, which will try to respond with some sort of response after request is completed. TaskA has to be around to receive that response. It's the client that doesn't care about it. – user981375 Dec 02 '15 at 04:37
-1

Without an example of what you have. I think you are looking for an Async with callback.

What you'd want to start the call to B without "awaiting" it so you can close your P1 Task and return then you'd want something like this.

Please have a look here, too: Can i use async without await in c#?

I hope that helps.

Community
  • 1
  • 1
thinklarge
  • 672
  • 8
  • 24