Tôi đang sử dụng ASP.NET MVC 5 và Identity Framework. Khi tôi gọi UserManager.UpdateAsync (...) của tôi eventhandlers trên ApplicationDbContext() SaveChanges sẽ chạy. Ở đây tôi đang sử dụng HttpContext.Current cho các mục đích khác nhau (đăng nhập và kiểm toán) vì vậy tôi phải nói người dùng hiện tại. Tuy nhiên, toàn bộ phương thức chạy trong một luồng công nhân, và ở đây HttpContext.Current là null.HttpContext.Current is null bên trong các phương thức của Identity Framework
Vấn đề lớn nhất là các phương thức "đồng bộ hóa" của UserManager chỉ bao quanh các phiên bản async, vì vậy các cuộc gọi được tuần tự hóa, nhưng các phương thức (và eventhandlers) vẫn chạy trong một chuỗi công nhân khác.
Xin lưu ý rằng vấn đề này không liên quan gì đến bối cảnh không đồng bộ/chờ đợi. Trong bộ điều khiển sau khi chờ đợi (hoặc gọi phiên bản 'đồng bộ') Tôi đã quay lại đúng HttpContext, ngay cả khi phương thức của bộ điều khiển đang tiếp tục trong một chủ đề khác. Đó là tốt.
Vì vậy, sự cố bên trong công nhân không đồng bộ sẽ chạy trong cả hai phiên bản "đồng bộ hóa" và không đồng bộ. Tôi nghĩ rằng tôi hiểu các hiện tượng (nhưng tôi không hài lòng với các phiên bản phương pháp 'đồng bộ' giả, phương thức đồng bộ hóa thực sự sẽ không thể hiện vấn đề này.) Tôi không biết cách giải quyết/giải quyết nó.
[btw: Sẽ không tự nhiên hơn khi triển khai các toán hạng của UserManager như các phiên bản đồng bộ thuần túy đơn giản, sau đó bọc chúng bằng các trình bao bọc đa luồng không đồng bộ ?. NẾU chúng ta tiếp tục thời trang không đồng bộ này mà không nghĩ chúng ta sẽ sớm phát minh ra toán tử gán async. Chi phí cho tôi hàng chục giờ (chỉ vấn đề này), và chi phí trên toàn thế giới zillion đô la, tôi chắc chắn trong nhiều trường hợp ít hơn giá của nó.]
Tiền thưởng: Chúng tôi đang nói về UserManager tác động khá biên, nhưng giống nhau nguyên tắc và vấn đề có thể áp dụng bất kỳ thư viện nào trong hộp thư (hộp đen cho bạn) mà tác giả không triển khai phiên bản đồng bộ hóa hoặc không quan tâm đến ngữ cảnh của trình điều khiển. Điều gì về EF, nó không phải là quá biên ... và những gì về DI container cơ sở hạ tầng instantiation như "phạm vi yêu cầu" hoặc "phạm vi phiên". Chắc chắn là chúng hoạt động sai nếu việc giải quyết xảy ra trong một luồng không có HttpContext.Current. Gần đây tôi đã làm mới SendGrid NuGet, và (như là một thay đổi phá vỡ) Deliver() phương pháp đi, và bây giờ chỉ DeliverAsync() là hiện tại ...
Tôi muốn có một cách đáng tin cậy an toàn, làm thế nào tôi có thể truy cập HttpContext bên trong công nhân này cho mục đích khai thác gỗ và kiểm toán.
Mẫu mã, bộ điều khiển 'đồng bộ' phiên bản:
[AcceptVerbs(HttpVerbs.Post)]
public virtual ActionResult Edit(ApplicationUser user)
{
// validation etc
// Update() seems to be only a poor wrapper around the async version, still uses a worker thread.
var result = UserManager.Update(user);
// Note: HttpContext is correct here so it is not an async/await problem
// error handling, creating ActionResult etc.
}
Mẫu mã, phiên bản điều khiển async:
[AcceptVerbs(HttpVerbs.Post)]
public virtual async Task<ActionResult> Edit(ApplicationUser user)
{
// validation etc
var result = await UserManager.UpdateAsync(user);
// Note: HttpContext is correct here so it is not an async/await problem
// error handling, creating ActionResult etc.
}
và xử lý sự kiện nơi HttpContext là null:
public ApplicationDbContext() : base("DefaultConnection", false)
{
InitializeAudit();
}
private void InitializeAudit()
{
var octx = ((IObjectContextAdapter) this).ObjectContext;
octx.SavingChanges +=
(sender, args) =>
{
// HttpContext.Current is null here
};
}
Bất kỳ ý tưởng nào?
Cân nhắc hiển thị mã ... –
Bạn có thể hiển thị mã cụ thể mà bạn đang yêu cầu không? – i3arnon
Làm thế nào về việc lưu trữ 'HttpContext.Current' trong một biến cục bộ trước khi tạo bất kỳ nhiệm vụ nào và chuyển nó đến các nhiệm vụ/chủ đề bằng cách nào đó. – EZI