2015-05-24 15 views
5

Tôi có một quy trình tôi muốn chạy trong nền. Điều này được thực hiện với một cú nhấp chuột vào một liên kết hành động.Quay lại Chế độ xem với Async Await

Hành động để gọi:

public async Task<ActionResult> ProcessRec() 
    { 
     await Task.Run(() => waitTimer()); 
     return RedirectToAction("Index", "Home"); 
    } 

    public void waitTimer() 
    { 
     Thread.Sleep(10000); 
    } 

Tuy nhiên điều này đợi cho đủ 10 giây trước khi chuyển hướng tôi "Index, Home" của tôi hành động. Tôi rất mới để Await/Async vì vậy tôi biết tôi đang giải thích một cái gì đó sai ở đây. Làm thế nào để ứng dụng quay trở lại hành động này, trong khi waitTimer đang thực hiện ở chế độ nền? Cảm ơn!!

+0

Bạn đang sử dụng phiên bản .NET nào. .NET 4.5.2 đã giới thiệu một tính năng để thực hiện việc này "chính xác" dễ dàng hơn. –

+1

Tôi đang sử dụng .NET 4.5 –

+0

Tôi đã chỉnh sửa tiêu đề của bạn. Vui lòng xem, "[Câu hỏi có nên bao gồm" thẻ "trong tiêu đề của họ không?] (Http://meta.stackexchange.com/questions/19190/)", trong đó sự đồng thuận là "không, họ không nên". –

Trả lời

4

await, như bạn đã phát hiện ra, chặn phản hồi trả lại cho người dùng trước khi hoàn thành. Thông thường bạn chỉ cần đặt công việc nền của bạn trên một luồng khác và đặt nó thành "lửa và quên" bằng cách không chờ đợi, tuy nhiên trong ASP.NET IIS sẽ tắt AppDomain không được sử dụng và Task.Run không thông báo cho IIS rằng chuỗi nền của bạn " đang sử dụng AppDomain "để chuỗi nền của bạn có thể bị chấm dứt bằng Thread.Abort() trong khi tắt AppDomain.

Nếu bạn đang sử dụng .NET 4.5.2 hoặc mới hơn, bạn có thể yêu cầu IIS bạn có một nhân viên nền mà bạn cần được giữ sống qua QueueBackgroundWorkItem. Bạn sẽ sử dụng nó như thế này

public ActionResult ProcessRec() 
    { 
     HostingEnvironment.QueueBackgroundWorkItem(waitTimer); 
     return RedirectToAction("Index", "Home"); 
    } 

    public void waitTimer(CancellationToken token) 
    { 
     Thread.Sleep(10000); 
    } 
    //You also could do 
    public async Task waitTimer2(CancellationToken token) 
    { 
     await Task.Delay(10000); 
    } 

Bây giờ điều này không đảm bảo rằng IIS sẽ không tắt miền ứng dụng của bạn, nhưng nó không để cho nó biết bạn đang ở giữa một cái gì đó và yêu cầu thời gian hơn khi nó cố gắng tắt nó (Bạn nhận được thêm 90 giây sau khi tắt máy bắt đầu hoàn thành tất cả các mục nền xếp theo mặc định).

Để biết thêm thông tin, hãy đọc this MSDN blog giới thiệu.

+0

Không có HostingEnvironment.QueueBackgroundWorkItem trong 4.5 – rnofenko

+1

Ông nói .NET 4.5.2. –

+0

Tôi cập nhật lên 4.5.2 và các công trình trên hoàn hảo cho nhu cầu của tôi! Nhiều đánh giá cao! –

1

Tôi đang suy nghĩ về việc gửi tin nhắn đến hàng đợi (như hàng đợi lưu trữ trên xe buýt/dịch vụ) để bạn có thể nhận phản hồi ngay lập tức.

Và sau đó tạo ra một dịch vụ khác để dequeue và xử lý tin nhắn (thực hiện nhiệm vụ chạy dài của bạn)

Ngoài ra nếu điều này là một trang web xanh (ứng dụng web), bạn có thể sử dụng công việc web!

Hy vọng điều đó sẽ hữu ích.

2

Tuy nhiên, điều này chờ 10 giây trước khi chuyển hướng tôi đến hành động "Chỉ mục, Trang chủ" của tôi.

Phải, đó là vì await không đồng bộ chờ hoàn thành hoạt động. Nó sẽ mang lại cho thread trở lại hồ bơi cho đến khi hoạt động hoàn tất.

Làm cách nào để ứng dụng trả lại hành động này trong khi waitTimer đang thực hiện trong nền?

Task.Run là nguy hiểm trong thực tế nó không đăng ký làm việc với IIS which can lead to problems. Thay vào đó, bạn có thể sử dụng BackgroundTaskManager hoặc HangFire đăng ký thực thi với ASP.NET:

BackgroundTaskManager.Run(() => { waitTimer() }; 
return RedirectToAction("Index", "Home"); 
+0

Hai thư viện liên kết là lựa chọn thay thế rất tốt nếu bạn không thể nâng cấp lên 4.5.2 để sử dụng 'QueueBackgroundWorkItem'. –

+0

@Scott Yeah, tôi thấy anh ấy nói .NET 4.5 :) –

Các vấn đề liên quan