这是我正在努力的流程,
这是我迄今取得的成就,
[Route("api/[controller]")]
public class PremController : Controller
{
private readonly myDbContext _context;
public PremController(myDbContext context)
{
_context = context;
}
[HttpGet]
public HttpResponseMessage Get()
{
Task.Factory.StartNew(() => DoWork());
return new HttpResponseMessage(HttpStatusCode.Accepted);
}
private void DoWork()
{
Delay(2000).ContinueWith(_ => GetProducts());
}
private void GetProducts()
{
var productUrls = _context.Products.Select(p => p.Url).ToArrayAsync();
}
static Task Delay(int milliseconds)
{
var tcs = new TaskCompletionSource<object>();
new Timer(_ => tcs.SetResult(null)).Change(milliseconds, -1);
return tcs.Task;
}
}
但是我收到的错误是myDbContext在新创建的任务完成之前被处理掉了。我该如何解决这个问题?
答案 0 :(得分:1)
这是因为您创建了即发即弃任务,没有同步上下文。如果您直接等待DoWork()
,则会保留同步上下文,从而确保不会处理上下文。更具体地说,您创建的任务在上下文的生命周期之外运行,由DI容器定义(很可能是请求范围的)。请求一旦完成,就会释放上下文,从而终止您的任务在请求之外尝试完成的工作。
长短不一,这是一个糟糕的设计,原因有很多。如果你需要做&#34;背景&#34;工作,应该卸载到一个完全不同的过程,而不仅仅是一个新的线程。在那里运行的代码应该负责维护自己的上下文,而不受Web应用程序中发生的事情的影响。 Task.Run
/ Task.Factory.StartNew
对于Web应用程序来说非常糟糕,因为它有一个有限的线程池,并且从该池启动新线程会降低服务器的总负载容量。
如果您发现自己想要在Web应用程序中启动新主题,请不要这样做。这几乎是普遍错误的。相反,请使用后台处理解决方案(如Hangfire或类似方法)安排工作。