2010-02-02 51 views
5

Tôi đang sử dụng 5 đối tượng BackgroundWorker chạy cùng một lúc cho một mục đích nhất định và tất cả chúng phải thay đổi cùng một nhãn. Làm thế nào để làm điều đó?BackgroundWorker truy cập đa luồng để tạo thành

Làm cách nào để sửa đổi biểu mẫu từ nhiều hơn một chuỗi? Và làm thế nào để tôi làm điều đó trong trường hợp tôi muốn thay đổi một chuỗi công cộng?

Trả lời

17

Sử dụng kiểm soát.Được thu hút với người được ủy quyền.

Trong thread công nhân nền của bạn, thay vì nói

label4.Text = "Hello"; 

nói

label4.Invoke(new Action(() => 
{ 
    label4.Text = "Hello"; 
} 
)); 

Tất cả mọi thứ bên trong {} thực thi trên chủ đề của kiểm soát, vì vậy bạn tránh được những ngoại lệ.

Điều này cho phép bạn thực hiện các thay đổi tùy ý cho giao diện người dùng của mình từ BackgroundWorker thay vì chỉ báo cáo tiến trình.

+0

ReportProgress cũng sẽ cho phép bạn thực hiện các thay đổi tùy ý cho giao diện người dùng. –

+0

làm thế nào để tôi gọi nó nếu nó đang xảy ra với một chuỗi công khai của mẫu của tôi? – Marcelo

+0

@Henk: ReportProgress sẽ chỉ cho phép BackroundWorker gửi một đối tượng "UserState" duy nhất, mà sau đó phải được xử lý bởi trình xử lý sự kiện ProgressChanged để thực sự cập nhật giao diện người dùng. Những gì tôi đã cố gắng để nói là với cách tiếp cận Invoke(), bạn có thể đặt mã cho bản cập nhật ngay bên trong phương thức mà bạn tạo BackgroundWorker ngay từ đầu, dẫn đến mã hiệu quả hơn và dễ đọc hơn. Đây là một quyết định thiết kế tất nhiên, với tất cả các sự cân bằng bình thường. – RobC

2

Bạn có thể sử dụng phương thức ReportProgress trong BackgroundWorker nơi bạn muốn nhãn thay đổi và viết mã thực tế trong ProgressChanged trình xử lý sự kiện.

+0

vấn đề là đây là một ngoại lệ cho thấy nhãn, vì vậy nó không phải mọi khi phương pháp chạy bởi các nền sẽ làm cho bất kỳ tương tác với các hình thức – Marcelo

+0

Bạn có thể sử dụng đề xuất của RaYell để đăng thông tin cho GUI mà sau đó có thể làm bản cập nhật chính nó. –

0

Hãy xem xét this answer. Nó không quan trọng nếu bạn có một, năm hoặc hàng ngàn chủ đề công nhân (trong ý nghĩa của khái niệm).

1

Bạn nên cảnh giác với việc gọi Invoke đồng bộ thay vì async BeginInvoke trên gui. Bạn sẽ sớm có một gui không phản hồi và cẩu thả dường như đang phải vật lộn để vẽ chính nó, cũng như tiềm năng cho deadlocks.
Tùy thuộc vào mức độ thường xuyên bạn cập nhật - và chuỗi chủ đề của bạn có thực sự cần phải đợi gui quay lại không? Điều đó nghe có vẻ giống như một vấn đề với mô hình của bạn.

1

Cũng như Control.BeginInvoke, bạn có thể xem SynchronizationContext.

Khi bạn đang tạo BackgroundWorkers, giả sử bạn đang tạo chúng từ chuỗi giao diện người dùng, bạn chuyển vào SynchronizationContext.Current cho người lao động. Khi BackgroundWorkers đã sẵn sàng để gọi lại thứ gì đó trên thread UI, họ gọi phương thức Synchronization.Post trên thể hiện SynchronizationContext được truyền vào khi chúng được tạo ra.

Có hai bài viết hay về SynchronizationContext herehere.