2010-08-06 26 views
6

Đôi khi khi BeginInvoke được gọi, phải mất hơn một giây để thực hiện phương thức ủy nhiệm.Delegate.BeginInvoke Delay

Điều gì có thể là lý do cho sự chậm trễ? Tôi nhận được vấn đề này 1 hoặc 2 lần một ngày trong một ứng dụng chạy liên tục.

Hãy giúp tôi.

Cảm ơn!

+2

Đây có phải là 'Control.BeginInvoke' hoặc 'Delegate.BeginInvoke' không? –

+2

Nó đang tạo một chủ đề mới - nhưng tôi không biết phải mất bao lâu. Có lẽ rất nhanh. –

+0

Tạo chủ đề mới tương đối đắt. –

Trả lời

7

Trình quản lý nhóm luồng đảm bảo rằng chỉ có nhiều chuỗi được phép thực hiện khi bạn có lõi CPU. Ngay sau khi hoàn thành, một số khác đang đợi trong hàng đợi được phép thực hiện.

Hai lần một giây, nó sẽ đánh giá lại những gì đang xảy ra với các chuỗi đang chạy. Nếu họ không hoàn thành, nó giả định rằng họ đang bị chặn và cho phép một thread chờ đợi để chạy. Trên CPU hai lõi điển hình, bạn sẽ nhận được hai luồng chạy ngay lập tức, chuỗi thứ ba bắt đầu sau một giây, chuỗi thứ 4 sau 1,5 giây, v.v.

Vâng, đó là lần thứ hai của bạn. Q & D sửa chữa là sử dụng ThreadPool.SetMinThreads(), nhưng đó là giải pháp sledgehammer. Vấn đề thực sự là chương trình của bạn đang sử dụng các chủ đề nhóm luồng cho các tác vụ dài hạn. Hoặc là vì chúng thực thi nhiều mã hoặc vì chúng chặn một số yêu cầu I/O. Sau này là trường hợp phổ biến hơn.

Cách giải quyết là không sử dụng chuỗi chủ đề cho chuỗi chặn như vậy nhưng sử dụng lớp Thread thay thế. Đừng làm điều này nếu các chủ đề đang thực sự đốt chu kỳ CPU, bạn sẽ làm chậm tất cả mọi thứ xuống. Dễ hiểu, bạn sẽ thấy 100% tải CPU ở Taskmgr.exe

+0

Xin chào Hans, Cảm ơn bạn đã trả lời. Có cách nào dễ dàng để hiểu luồng thread nào đang chặn trên IO hoặc lấy nhiều chu kỳ CPU hơn. Cảm ơn! – Maanu

+0

Nếu bạn không biết thì bạn sử dụng quá nhiều. Bạn có thể tìm hiểu bằng cách đăng nhập bắt đầu + kết thúc. –

2

Bạn có thể đặt mức độ ưu tiên của BeginInvoke không?

http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcherpriority.aspx

Bạn có các cuộc gọi BeginInvoke khác đang chờ?

"Nếu nhiều cuộc gọi BeginInvoke được thực hiện tại cùng DispatcherPriority, chúng sẽ được thực hiện theo thứ tự các cuộc gọi được thực hiện".

http://msdn.microsoft.com/en-us/library/ms591206.aspx

+0

Nó là Delegate.BeginInvoke. Tôi đo sự khác biệt bằng cách đăng nhập. Có một mục nhập nhật ký trước khi gọi BeginInvoke. Một mục nhật ký cũng có trong phương thức Ủy quyền cũng .. – Maanu

4

Vì bạn đang sử dụng Delegate.BeginInvoke sau đó bạn, gián tiếp, bằng cách sử dụng ThreadPool. Các ThreadPool tái chế các chủ đề hoàn thành và cho phép chúng được tái sử dụng mà không phải trải qua các chi phí xây dựng các chủ đề mới và xé chuỗi hoàn thành xuống.

Vì vậy, khi bạn sử dụng Delegate.BeginInvoke bạn đang thêm phương thức được gọi vào hàng đợi, ngay sau khi ThreadPool cho rằng nó có một chuỗi có sẵn cho công việc của bạn, nó sẽ thực thi. Tuy nhiên, nếu ThreadPool không có chủ đề nào thì bạn sẽ bị bỏ lại.

System.Threading.ThreadPool có một số thuộc tính và phương pháp để hiển thị số lượng chủ đề có sẵn, tối đa, v.v. Tôi sẽ thử theo dõi những số liệu đó để xem có vẻ như ThreadPool đang bị mỏng hay không.

Nếu trường hợp đó thì độ phân giải tốt nhất là đảm bảo rằng ThreadPool chỉ được sử dụng cho các tác vụ ngắn ngủi (nhỏ). Nếu nó đang được sử dụng cho các nhiệm vụ chạy dài thì các nhiệm vụ đó phải được sửa đổi để sử dụng chuỗi chuyên dụng của riêng chúng hơn là chiếm ThreadPool.

+0

Xin chào STW, Làm thế nào để bạn giám sát các tham số ThreadPool? Thăm dò ý kiến ​​hay cái gì khác? Cảm ơn! – Maanu

+0

Bạn có thể sử dụng bộ đếm thời gian đơn giản, chẳng hạn như 'System.Threading.Timer' để gọi phương thức có thể thu thập và báo cáo trạng thái threadpool – STW

+0

... Tôi không biết điều này, nhưng nó cũng có vẻ như có thể quầy hiệu suất có sẵn đặc biệt để thực hiện việc này: http://msdn.microsoft.com/en-us/library/ff650682.aspx – STW

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