2012-01-18 24 views
9

Tôi có một hành động MVC chạy dài (4-10 giây) chạy báo cáo từ cuộc gọi AJAX. Trong khi nó chạy người dùng có thể thay đổi các tham số và chạy một cái gì đó khác, vì vậy tôi hủy bỏ yêu cầu AJAX trước khi thực hiện một số khác.Làm thế nào để bạn hủy bỏ một phía máy khách hành động MVC dài chạy MVAX (trong javascript)?

Vì vậy, ví dụ (ví dụ trong jQuery nhưng vấn đề xảy ra bất kể):

// If we have an active request and it's not complete 
if(dataRequest && dataRequest.readyState != 'complete') 
{ 
    dataRequest.abort(); 
} 

dataRequest = $.ajax(...); 

Khách hàng bên này dường như làm việc tốt, nhưng yêu cầu hủy vẫn chạy trên máy chủ. Ví dụ: nếu báo cáo mất 10 giây và tôi hủy một báo cáo và bắt đầu một báo cáo khác thì yêu cầu thứ hai mất 20 giây.

Tôi nghĩ rằng đây là do sự session level locking:

[Nếu] hai yêu cầu đồng thời được thực hiện đối với cùng một phiên (bằng cách sử dụng cùng giá trị SessionID), yêu cầu đầu tiên được truy cập độc quyền để sự thông tin phiên. Yêu cầu thứ hai chỉ thực hiện sau khi yêu cầu đầu tiên kết thúc.

Vì vậy, yêu cầu thứ hai không thể truy cập phiên cho đến khi phiên đầu tiên kết thúc. Việc sử dụng các hành động MVC không đồng bộ dường như không thực hiện được điều này vì hành động vẫn cần để có thể thay đổi phiên.

Có thể dừng một hành động và bắt đầu một hành động tiếp theo mà không sử dụng AsyncController hoặc [SessionState(SessionStateBehavior.ReadOnly)]?

Nếu không được yêu cầu cả hai?

Trả lời

4

Khi nó quay ra câu trả lời hoàn chỉnh cần hai điều:

Thứ nhất (nhờ Darin cho confirming it) phiên bản chất khóa các trang được thực hiện một sau khi khác. Further investigation đã chỉ ra đây là một vấn đề chung chung hơn với các phiên ASP.Net - họ chỉ không thể xử lý đồng thời lạc quan.

Thứ hai, yêu cầu bị hủy cần kiểm tra xem máy khách có được kết nối hay không. Có những tình huống mà bạn có thể muốn tiếp tục (như hỏa hoạn và quên hành động ASP) nhưng trong trường hợp này nếu khách hàng không còn chờ báo cáo thì chúng tôi không tiếp tục xử lý nó.

Đây là có sẵn như là một property of the response: this.Response.IsClientConnected

Vì vậy, để hủy bỏ một cách hiệu quả hành động phía máy chủ của tôi khi jQuery yêu cầu nó tôi đã phải viết phiên xử lý của riêng mình và thêm kiểm tra thường xuyên chống lại this.Response.IsClientConnected.

+1

Hãy cẩn thận dựa vào 'IsClientConnected' vì nó có thể là một vấn đề hiệu suất nghiêm trọng để kiểm tra nó, xem http://stackoverflow.com/questions/9094735/when-is-response-isclientconnected-slow – Keith

+0

Hi Keith! Tôi có một vấn đề tương tự nhưng không thể giải quyết ngay cả với câu trả lời của bạn, (http://stackoverflow.com/questions/29235850/how-to-abort-long-running-ajax-request-in-net-mvc-4) Có cách nào giúp tôi không? Hoặc bạn có thể đăng một mã mẫu của bạn để kích hoạt 'this.Response.IsClientConnected' –

4

[SessionState(SessionStateBehavior.ReadOnly)] hoặc tắt phiên hoàn toàn là đủ để cho phép truy cập đồng thời vào các hoạt động của bộ điều khiển từ cùng một phiên. Vì vậy, yêu cầu thứ hai (từ cùng một phiên) không cần phải chờ cho lần đầu tiên hoàn thành trước khi được xử lý. Theo như hủy bỏ các hành động đầu tiên trên máy chủ là có liên quan, tốt, đó sẽ là khó khăn hơn. Bạn sẽ phải liên kết mỗi tác vụ một id duy nhất và khi một nhiệm vụ mới được bắt đầu trả về id tác vụ này cho máy khách. Sau đó, khi bạn hủy yêu cầu AJAX trên máy khách bằng cách gọi .abort(), bạn có thể kích hoạt một yêu cầu AJAX khác cho một số hành động điều khiển khác và chuyển nó cho id tác vụ duy nhất. Bản thân hành động điều khiển này sẽ thiết lập một số cờ chung để chỉ ra hành động đầu tiên dừng lại.

TPL có hỗ trợ hủy tích hợp sẵn mà bạn có thể xem xét để đơn giản hóa điều đó để tránh cấu trúc dữ liệu được chia sẻ giữa 2 cấu hình sẽ đồng bộ hóa chúng.

+0

Tôi đã sử dụng TPL để thực hiện rất nhiều công việc cần dành thời gian - tôi đang thực hiện khoảng 25 giây giá trị mã liên tục chạy dài trong khoảng 4-10 giây song song. Tuy nhiên việc sử dụng nó để xử lý việc hủy bỏ có vẻ như tái phát minh ra bánh xe; tại sao yêu cầu mới cần phải thông báo cho yêu cầu cũ (vẫn đang chạy) để hủy bỏ khi nó đã bị hủy? – Keith

+1

@Keith, đó không phải là yêu cầu mới sẽ báo cho người cũ hủy bỏ. Bạn phải gửi một yêu cầu AJAX đặc biệt mới để yêu cầu máy chủ hủy bỏ việc xử lý một tác vụ cụ thể. Khi bạn làm 'dataRequest.abort();' bạn chỉ hủy bỏ yêu cầu AJAX nhưng nếu bạn muốn hủy bỏ việc xử lý phía máy chủ, bạn cần phải làm nhiều công việc hơn thế. –

+0

Hmm, vì vậy IIS không biết rằng yêu cầu đã bị hủy ở cấp độ vận chuyển? Tôi đã có thể mong đợi các chủ đề trang được hủy bỏ ở cấp IIS/ASP khi kết nối chờ đợi được chấm dứt ở cấp độ vận chuyển. – Keith

1

.abort() chỉ là hủy bên phía khách hàng. Nếu bạn muốn theo dõi nó ở phía máy chủ, một trong những cách tốt nhất để làm điều đó là bình chọn cho tài sản IsClientConnected, sẽ cho bạn biết tình trạng giao tiếp ajax là gì.

+1

Xem câu trả lời được chấp nhận và câu hỏi ban đầu. Câu trả lời này không thêm bất cứ điều gì chưa được nêu. Cũng rất cẩn thận khi sử dụng 'IsClientConnected' vì nó có thể là vấn đề hiệu năng nghiêm trọng để kiểm tra nó, xem http://stackoverflow.com/questions/9094735/when-is-response-isclientconnected-slow (dường như nó có thể có giá lên đến Tos để kiểm tra nó, nhưng không ai có thể xác nhận) – Keith

+0

Bạn nói đúng, tôi đã đọc bài đăng của bạn và tôi phải sửa lại solutiuon của mình. – Dave

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