是什么阻止了这项任务的长期运行?

时间:2012-11-20 22:34:32

标签: c# multithreading asp.net-mvc-3 razor task

出于测试目的,我直接在.cshtml页面的剃刀块中使用它。

@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);
}

我曾期望它每秒写一次带有“Hello”文本的跨度。它有时会写“Hello”,但不是每次都写,甚至不是。为什么这个任务没有长期运行?

2 个答案:

答案 0 :(得分:3)

您看到不同结果的原因是因为任务是异步运行的,并且如果响应对象在您的任务有机会写入之前完成,则taks将抛出异常并且它将终止您可以执行的唯一方式这是在Writer()方法的末尾添加Task.WaitAll()。

这样可行,但页面不会停止加载内容。

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());

答案 1 :(得分:1)

这是另一个选项,它使用自定义ActionResult,它首先处理控制器(默认结果),然后启动任务。

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);
    }
}

在您的控制器中

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