简体   繁体   中英

What prevents this task from being long running?

For testing purposes, I am using this directly inside of a razor block in a .cshtml page.

@functions{
    public class Inline
    {
        public HttpResponseBase r { get; set; }
        public int Id { get; set; }
        public List<System.Threading.Tasks.Task> tasks = new List<System.Threading.Tasks.Task>();

        public void Writer(HttpResponseBase response)
        {
            this.r = response;
            tasks.Add(System.Threading.Tasks.Task.Factory.StartNew(
                    () =>
                    {
                        while (true)
                        {
                            r.Write("<span>Hello</span>");
                            System.Threading.Thread.Sleep(1000);
                        }
                    }
            ));
        }
    }
}

@{
    var inL = new Inline();
    inL.Writer(Response);
}

I had expected it to write a span with the text "Hello" once every second. It will write "Hello" once sometimes, but not every time or even most times. Why isn't this task long running?

The reason you are seeing different result is because the task is running asynchronously and if the response object is completed before your task gets a chance to write on it, the taks will throw exception and it will terminate the only way you can do this is if you add Task.WaitAll() at the end of the Writer() method.

This will work but the page will not stop loading content.

this.r = response;
tasks.Add(System.Threading.Tasks.Task.Factory.StartNew(
        () =>
        {
            while (true)
            {
                r.Write("<span>Hello</span>");
                r.Flush(); // this will send each write to the browser
                System.Threading.Thread.Sleep(1000);
            }
        }

));

//this will make sure that the response will stay open
System.Threading.Tasks.Task.WaitAll(tasks.ToArray());

Here is another option this one uses a custom ActionResult , it first process the controller (the default result) after that is done it starts the task.

public class CustomActionResult:ViewResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        base.ExecuteResult(context);
        var t =  Task.Factory.StartNew(() =>
             {

                  while (true)
                   {
                      Thread.Sleep(1000);
                      context.HttpContext.Response.Write("<h1>hello</h1>");
                      context.HttpContext.Response.Flush();
                   }
            });

        Task.WaitAll(t);
    }
}

In your controller

public class HomeController : Controller
{
    public ActionResult Index()
    {
       return new CustomActionResult();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM