gpt4 book ai didi

c# - 尝试异步方法失败

转载 作者:行者123 更新时间:2023-11-30 18:33:45 28 4
gpt4 key购买 nike

我有一个使用 Entity Framework (4.3.1 代码优先)的 MVC3/.NET 4 应用程序

我已将 EF 包装到 Repository/UnitOfWork 模式中,如此处所述...

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

通常,如文章中所述,当我需要创建新记录时,我一直在这样做......

public ActionResult Create(Course course)
{
unitOfWork.CourseRepository.Add(course);
unitOfWork.Save();
return RedirectToAction("Index");
}

然而,当需要的不仅仅是将记录保存到数据库时,我将逻辑包装到我称之为 IService 的东西中。例如……

private ICourseService courseService;
public ActionResult Create(Course course)
{
courseService.ProcessNewCourse(course);
return RedirectToAction("Index");
}

在我的一项服务中,我有如下内容……

public void ProcessNewCourse(Course course)
{
// Save the course to the database…
unitOfWork.CourseRepository.Add(course);
unitOfWork.Save();

// Generate a PDF that email some people about the new course being created, which requires more use of the unitOfWork…
var someInformation = unitOfWork.AnotherRepository.GetStuff();
var myPdfCreator = new PdfCreator();

IEnumerable<People> people = unitOfWork.PeopleRepository.GetAllThatWantNotifiying(course);

foreach(var person in people)
{
var message = “Hi ” + person.FullName;
var attachment = myPdfCreator.CreatePdf();
etc...
smtpClient.Send();
}
}

以上不是实际代码(我的应用程序与类(class)无关,我使用的是 View 模型,并且我已将 PDF 创建和电子邮件消息分离到其他类中),但要点是要点就如上!

我的问题是生成 PDF 并将其通过电子邮件发送出去需要一些时间。用户只需要知道记录已保存到数据库中,所以我想将代码放在 unitOfWork.Save(); 下方。变成一个异步方法。然后可以重定向用户,服务器可以愉快地花时间处理电子邮件、附件以及我要求它进行后保存的任何其他内容。

这就是我挣扎的地方。

我已经尝试了一些东西,当前是 ICourseService 中的以下内容......

public class CourseService : ICourseService
{

private delegate void NotifyDelegate(Course course);
private NotifyDelegate notifyDelegate;

public CourseService()
{
notifyDelegate = new NotifyDelegate(this.Notify);
}

public void ProcessNewCourse(Course course)
{
// Save the course to the database…
unitOfWork.CourseRepository.Add(course);
unitOfWork.Save();

notifyDelegate.BeginInvoke(course);
}

private void Notify(Course course)
{
// All the stuff under unitOfWork.Save(); moved here.
}
}

我的疑问/问题

我随机收到错误:“已经有一个打开的 DataReader 与此命令关联,必须先将其关闭。”在 Notify() 方法中。

  1. 这是否与我尝试共享 unitOrWork 并因此跨线程共享 dbContext 这一事实有关?

  2. 如果是这样,有人可以解释一下为什么这是个问题吗?

  3. 我应该为 Notify 方法提供一个新的 unitOfWork 实例吗?

  4. 我是否使用了正确的模式/类来异步调用方法?或者我应该使用类似...的东西吗?

    new System.Threading.Tasks.Task(() => { Notify(course); }).Start();

    我必须说我对异步、并行和并发这些术语感到非常困惑!!

  5. 任何指向文章的链接(白痴的 c# async)将不胜感激!!

非常感谢。

更新:

多一点挖掘让我进入了这个 SO 页面:https://stackoverflow.com/a/5491978/192999这说...

“请注意,尽管 EF 上下文不是线程安全的,即您不能在多个线程中使用相同的上下文。”

...那么我是否正在努力实现不可能的目标?这是否意味着我应该为我的新线程创建一个新的 IUnitOfWork 实例?

最佳答案

您可以创建一个轮询后台线程,该线程独立于主流程执行冗长的操作。此线程可以扫描数据库以查找新项目(或标记为处理的项目)。这个解决方案非常简单,即使您的应用程序崩溃也能确保作业完成(当轮询线程再次启动时它会被拾起)。

你也可以使用 Synchronised Queue如果请求“丢失”并不可怕,万一您的应用程序在请求文档之后和生成/发送之前崩溃。

有一件事几乎是肯定的 - 正如 rikitikitik 所说 - 您将需要使用一个新的工作单元,这意味着一个单独的事务。

您还可以查看 Best threading queue example / best practice .

关于c# - 尝试异步方法失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17070415/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com