出于测试目的,我直接在.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”,但不是每次都写,甚至不是。为什么这个任务没有长期运行?
答案 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();
}
}