6

How to create Async ActionResult to create an async-awta model for the following...

 2 years ago
source link: https://www.codesd.com/item/how-to-create-async-actionresult-to-create-an-async-awta-model-for-the-following-query-logic.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

How to create Async ActionResult to create an async-awta model for the following query logic?

advertisements

I have a loop that actually waits for some process for completion of a Job and returns result.

I have MyRestClient.FetchResult(id) and MyRestClient.FetchResultAsync(id) both available to me, which fetches result from some remote service and returns boolean value if it is complete.

 public class StatusController: ActionController {

    public ActionResult Poll(long id){
        return new PollingResult(()=>{
            return MyRestClient.FetchResult(id) == SomethingSuccessful;
        });
    }
 }

 public class PollingResult : ActionResult{

     private Func<bool> PollResult;

     public PollingResult(Func<bool> pollResult){
         this.PollResult = pollResult;
     }

     public override void ExecuteResult(ControllerContext context)
     {
         Response = context.HttpContext.Response;
         Request = context.HttpContext.Request;

         // poll every 5 Seconds, for 5 minutes
         for(int i=0;i<60;i++){
             if(!Request.IsClientConnected){
                 return;
             }
             Thread.Sleep(5000);
             if(PollResult()){
                  Response.WriteLine("Success");
                  return;
             }

             // This is a comet, so we need to
             // send a response, so that browser does not disconnect
             Response.WriteLine("Waiting");
             Response.Flush();
         }

         Response.WriteLine("Timeout");

     }
 }

Now I am just wondering if there is anyway to use Async Await to improve this logic because this thread is just waiting for every 5 seconds for 5 minutes.

Update

Async Task pattern usually finishes all work before sending result back to client, please note, if I do not send intermediate responses back to client in 5 seconds, client will disconnect.

Reason for Client Side Long Poll

Our web server is on high speed internet, where else clients are on low end connection, making multiple connections from client to our server and then relaying further to third party api is little extra overhead on client end.

This is called Comet technology, instead of making multiple calls in duration of 5 seconds, keeping a connection open for little longer is less resource consuming.

And of course, if client is disconnected, client will reconnect and once again wait. Multiple HTTP connections every 5 seconds drains battery life quicker compared to single polling request


First, I should point out that SignalR was designed to replace manual long-polling. I recommend that you use it first, if possible. It will upgrade to WebSockets if both sides support it, which is more efficient than long polling.

There is no "async ActionResult" supported in MVC, but you can do something similar via a trick:

public async Task<ActionResult> Poll()
{
  while (!IsCompleted)
  {
    await Task.Delay(TimeSpan.FromSeconds(5));
    PartialView("PleaseWait").ExecuteResult(ControllerContext);
    Response.Flush();
  }

  return PartialView("Done");
}

However, flushing partial results goes completely against the spirit and design of MVC. MVC = Model, View, Controller, you know. Where the Controller constructs the Model and passes it to the View. In this case you have the Controller is directly flushing parts of the View.

WebAPI has a more natural and less hackish solution: a PushStreamContent type, with an example.

MVC was definitely not designed for this. WebAPI supports it but not as a mainstream option. SignalR is the appropriate technology to use, if your clients can use it.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK