2008-08-13 30 views

Trả lời

10

Vì bạn có thể dễ dàng kết thúc bằng bế tắc (trong số các vấn đề khác).

Đối với exmaple, chuỗi phụ của bạn có thể đang cố gắng cập nhật điều khiển giao diện người dùng, nhưng điều khiển giao diện người dùng sẽ chờ tài nguyên bị khóa bởi chuỗi thứ cấp sẽ được giải phóng, vì vậy cả hai luồng sẽ chờ kết thúc. Như những người khác đã nhận xét tình trạng này không phải là duy nhất cho mã UI, nhưng đặc biệt phổ biến.

Trong các ngôn ngữ khác như C++ bạn được tự do thử và thực hiện điều này (không có ngoại lệ được ném như trong WinForms), nhưng ứng dụng của bạn có thể đóng băng và ngừng phản hồi nếu xảy ra bế tắc. Ngẫu nhiên, bạn có thể dễ dàng nói với chuỗi giao diện người dùng mà bạn muốn cập nhật một điều khiển, chỉ cần tạo một đại biểu, sau đó gọi phương thức BeginInvoke (không đồng bộ) trên điều khiển đó chuyển nó cho đại biểu của bạn. Ví dụ.

myControl.BeginInvoke(myControl.UpdateFunction); 

Đây là tương đương với làm một C++/MFC PostMessage từ một sợi công nhân

+3

Tôi không chắc tại sao câu trả lời này được chấp nhận. Đây không phải là câu trả lời đúng. Deadlocks có thể xảy ra bất cứ khi nào bạn có nhiều chủ đề. Không có gì vốn có trong các chương trình GUI khiến chúng có nhiều khả năng xảy ra hơn. Hơn nữa, chúng có thể dễ dàng xảy ra ngay cả khi bạn sử dụng BeginInvoke(). Câu trả lời của Brian Ensink là câu trả lời đúng. – mhenry1384

+1

-1: chờ đợi tài nguyên bị khóa không phải là vấn đề. Vấn đề là điều kiện chủng tộc, tồn tại với số lượng lớn trong bất kỳ mã nào không được thiết kế để sử dụng trong môi trường đa luồng. Bạn thậm chí có thể kiểm tra điều này bằng cách đặt [CheckForIllegalCrossThreadCalls] (http://msdn.microsoft.com/en-us/library/system.windows.forms.control.checkforillegalcrossthreadcalls (VS.80) .aspx) thành false và quan sát bế tắc - hoạt động miễn phí, cho đến khi điều gì đó buồn cười xảy ra. –

1

Đó là do đó bạn không có hai thứ cố cập nhật điều khiển cùng một lúc. (Điều này có thể xảy ra nếu CPU chuyển sang luồng khác ở giữa ghi/đọc) Cùng một lý do bạn cần sử dụng mutexes (hoặc một số đồng bộ hóa khác) khi truy cập các biến được chia sẻ giữa nhiều luồng.

Edit:

Trong các ngôn ngữ khác như C++ bạn miễn phí để thử và làm được điều này (không có một ngoại lệ bị ném như trong WinForms), nhưng bạn sẽ kết thúc học cứng đường!

Ahh vâng ... tôi chuyển đổi giữa C/C++ và C# và do đó nhiều hơn một chút chung thì tôi nên đã, xin lỗi ... Anh là chính xác, bạn có thể làm điều này trong C/C++, nhưng nó sẽ trở lại để cắn bạn!

2

Quay trở lại 1.0/1.1 không phải ngoại lệ được ném trong gỡ lỗi, những gì bạn có thay vì là một gián đoạn kịch bản thời gian chạy treo . Tốt đẹp! :) Vì vậy với 2.0 họ đã thực hiện kịch bản này ném một ngoại lệ và khá đúng như vậy.

Lý do thực sự cho điều này có thể (như Adam Haile nói) một số loại vấn đề đồng thời/khóa. Lưu ý rằng api .NET bình thường (chẳng hạn như TextBox.Text = "Hello";) kết thúc các lệnh SEND (yêu cầu hành động ngay lập tức) có thể tạo ra các vấn đề nếu được thực hiện trên một chuỗi riêng biệt từ một hành động cập nhật. Sử dụng Invoke/BeginInvoke sử dụng POST thay cho hàng đợi hành động.

Thông tin thêm về SEND và POST here.

1

Cũng sẽ cần phải thực hiện đồng bộ hóa trong các hàm cập nhật nhạy cảm với việc được gọi đồng thời. Làm điều này cho các yếu tố giao diện người dùng sẽ tốn kém ở cả cấp ứng dụng và hệ điều hành và hoàn toàn dư thừa cho phần lớn mã.

Một số API cung cấp cách thay đổi quyền sở hữu chuỗi hiện tại của hệ thống để bạn có thể tạm thời (hoặc vĩnh viễn) cập nhật hệ thống từ các chủ đề khác mà không cần phải liên lạc với chủ đề liên thông.

0

Tôi nghĩ đây là một câu hỏi tuyệt vời - và tôi nghĩ cần có câu trả lời tốt hơn.

Chắc chắn lý do duy nhất là có cái gì đó trong một khuôn khổ ở đâu đó không an toàn với chủ đề. Nó có phải là vấn đề với .NET hay Win32 - và tại sao không có một sự thúc đẩy để sửa chữa nguồn thay vì thực thi cái gì, với tôi, cảm thấy như một công việc khó chịu xung quanh?

Bất kỳ ai biết vấn đề cơ bản thực sự ở đâu?

23

Tôi nghĩ rằng đây là một câu hỏi tuyệt vời - và tôi nghĩ rằng cần có câu trả lời tốt hơn .

Chắc chắn lý do duy nhất là có là nội dung nào đó trong khung công tác ở đâu đó không an toàn với chủ đề.

"Điều gì đó" gần như là mọi thành viên cá thể đơn lẻ trên mọi điều khiển đơn trong System.Windows.Forms.

Tài liệu MSDN cho nhiều điều khiển trong System.Windows.Forms, nếu không phải tất cả trong số chúng, hãy nói "Bất kỳ thành viên tĩnh công cộng (Được chia sẻ trong Visual Basic) nào thuộc loại này là an toàn chủ đề. là chủ đề an toàn. "

này có nghĩa là các thành viên dụ như TextBox.Text {get; set;} không reentrant.

Làm cho mỗi thành viên trong ví dụ này an toàn có thể giới thiệu rất nhiều chi phí mà hầu hết các ứng dụng không cần. Thay vào đó, các nhà thiết kế của khung công tác .Net đã quyết định và tôi nghĩ một cách chính xác, rằng gánh nặng của việc đồng bộ hóa quyền truy cập vào các điều khiển biểu mẫu từ nhiều luồng nên được đặt vào lập trình viên.

[Chỉnh sửa]

Mặc dù câu hỏi này chỉ hỏi "tại sao" ở đây là một liên kết đến một bài viết giải thích "làm thế nào":

Làm thế nào để: Thực hiện cuộc gọi Thread-an toàn để Windows Forms Controls trên MSDN

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

+1

Nó hoàn toàn có thể được reentrant nhưng không an toàn thread. Xem xét (f) => {x + = 1; f (x); x - = 1; } đó là tốt lên để tràn nếu f (x) reenters lambda trên một sợi nhưng chủng tộc trên x nếu đa luồng. –

7

Mặc dù nó có vẻ hợp lý câu trả lời Johns là không đúng. Trong thực tế, ngay cả khi sử dụng Invoke bạn vẫn không an toàn không chạy vào tình huống chết khóa. Khi xử lý các sự kiện được kích hoạt trên một luồng nền bằng Invoke, thậm chí có thể dẫn đến vấn đề này.


Lý do thực sự có nhiều việc phải làm với điều kiện chủng tộc và đặt trở lại trong thời gian Win32 cổ đại. Tôi không thể giải thích chi tiết ở đây, từ khóa là máy bơm tin nhắn, sự kiện WM_PAINT và sự khác biệt tinh tế giữa "SEND" và "POST".


Thông tin bổ sung có thể được tìm thấy ở đây herehere.

0

Hmm Tôi không chắc lắm nhưng tôi nghĩ rằng khi chúng tôi có một điều khiển tiến bộ như thanh chờ, thanh tiến trình, chúng tôi có thể cập nhật giá trị của chúng từ một chuỗi khác và mọi thứ hoạt động tốt mà không gặp bất kỳ sự cố nào.

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