ASP.NET MVC:新线程中的异常呈现视图

时间:2012-08-16 22:14:42

标签: asp.net asp.net-mvc view multithreading

我想在我的ASP.NET应用程序中创建一个手动触发的进程,并将向用户发送一堆电子邮件。由于此过程需要一段时间,因此我创建了一个新线程来发送这些消息并防止在我的Web应用程序中超时。 (我知道如果应用程序池被回收或应用程序中存在未处理的异常,这很容易出错,但这是另一个主题。)

为此,我正在做这样的事情:

public ActionResult SendMessages()
{
  Task.Factory.StartNew(() => { SendMessagesLongRunningProcess(); });
  return View();
}

在长时间运行的进程中,我正在尝试呈现HTML电子邮件的视图并发送它。像这样:

private void SendMessagesLongRunningProcess()
{
  var users = GetUsers();
  foreach (var user in users)
  {
    string message = RenderView("EmailMessage", user);
    SendEmail(user.email, message);
  }
}

现在,我知道我的RenderView方法工作得很好,因为我用它来渲染其他地方的电子邮件视图。问题是当我尝试在新线程中执行它时,就像我在这里所做的那样。 这是我的RenderView方法:

    public string RenderView(string viewName, object model)
    {
        ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindView(ControllerContext, viewName, null);
            var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
            viewResult.View.Render(viewContext, sw);
            return sw.GetStringBuilder().ToString();
        }
    }

我得到的错误是:

Value does not fall within the expected range.

调用viewResult.View.Render方法时。

我猜这与控制器上下文在新线程中不再有效这一事实有关,但我不确定。

那么,解决这个问题的最佳方法是什么?我有哪些替代方案?

由于

1 个答案:

答案 0 :(得分:6)

  

我猜这与控制器上下文的事实有关   在新帖子中不再有效,但我不确定。

正。

  

那么,解决这个问题的最佳方法是什么?

从其他进程发送电子邮件,而不是ASP.NET MVC应用程序。

  

我有哪些替代方案?

一种可能性是使用RazorEngine

private void SendMessagesLongRunningProcess()
{
    var users = GetUsers();
    foreach (var user in users)
    {
        string view = Server.MapPath("~/Views/MailTemplates/SomeTemplate.cshtml");
        string template = System.IO.File.ReadAllText(view);
        string message = Razor.Parse(template, user);
        SendEmail(user.email, message);
    }
}

您也可以结帐MvcMailer并异步发送电子邮件(请查看分步指南的Send Email Asynchronously部分。)