【发布时间】:2019-03-05 19:32:11
【问题描述】:
以下代码适用于将 Razor 视图呈现为字符串:
///
/// url: /api/createHtml
///
public ActionResult CreateHtml()
{
// Heavy calculations
MyModel myModel = new MyModel();
myModel.Feature1 = ...;
myModel.Feature2 = ...;
myModel.Feature3 = ...;
ViewData.Model = myModel;
using (var stringWriter = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, "MyView");
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, stringWriter);
viewResult.View.Render(viewContext, stringWriter);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
string html = stringWriter.GetStringBuilder().ToString();
byte[] htmlBytes = Encoding.ASCII.GetBytes(html);
System.IO.File.WriteAllBytes(Server.MapPath("~/temp/foo.html"), htmlBytes);
}
return JSON(new
{
error = false,
message = "Your view is available at temp/foo.html"
});
}
上述代码同步运行,这意味着对/api/createHtml/ 的AJAX 请求将在创建temp/foo.html 文件时结束。
我想异步执行此操作:这意味着 AJAX 请求会快速返回给用户,并带有如下消息:“您的视图将在 temp/foo.html”。然后用户必须检查文件是否准备好(通过简单地轮询临时目录[或使用其他方法,在这个问题中并不重要])
所以,当我在 Task 中尝试相同的代码时,它不起作用:
///
/// url: /api/createHtml
///
public ActionResult CreateHtml()
{
new Task(() =>
{
// Heavy calculations
MyModel myModel = new MyModel();
myModel.Feature1 = ...;
myModel.Feature2 = ...;
myModel.Feature3 = ...;
ViewData.Model = myModel;
using (var stringWriter = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, "MyView");
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, stringWriter);
viewResult.View.Render(viewContext, stringWriter); // <--- Problem
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
string html = stringWriter.GetStringBuilder().ToString();
byte[] htmlBytes = Encoding.ASCII.GetBytes(html);
System.IO.File.WriteAllBytes(Server.MapPath("~/temp/foo.html"), htmlBytes);
}
}).Start();
return JSON(new
{
error = false,
message = "Your view _WILL BE_ available at temp/foo.html"
});
}
它不起作用,因为它在viewResult.View.Render(...) 处引发异常
值不在预期范围内。
看来viewContext传递给viewResult.View.Render(...)在新线程中不再有效,如下图:ASP.NET MVC: Exception rendering view in new thread
是否有在 Task 中呈现视图的解决方法?
我知道我可以使用“RazorEngine”,这是一个免费的库,可以在没有所有控制器的情况下呈现剃刀视图,但我更喜欢使用本机代码来重新利用代码。
发布编辑:
少数答案认为我想使用“等待异步”。 我没有。我不想等待任务完成。
【问题讨论】:
-
您是否尝试过改用
Task.Run(() => { your code })?这应该只是在线程池上安排任务。如果它是一个长时间的任务,你也可以使用 TaskCreationOptions.LongRunning 选项(在这种情况下它不会使用池) -
我会试试的。但它和
.Start()有什么不同吗? -
您声明调试器无故停止。你看过你的应用程序输出吗?您是否尝试过在 VS 中启用设置以捕获所有异常?
-
尝试在
Task构造函数参数中添加try-catch块,看看是否抛出任何异常。
标签: asp.net-mvc