2009-03-05 46 views
9

Gần đây tôi đã cố gắng sử dụng backgroundworker thay vì "cổ điển" chủ đề và tôi nhận ra rằng nó gây ra, ít nhất là cho tôi, nhiều vấn đề hơn giải pháp. Tôi có một backgroundworker chạy một đồng bộ đọc (trong trường hợp này từ serialPort) và bị chặn khoảng 30 giây trong 1 dòng mã, sau đó cancelpending không phải là giải pháp. Tôi thấy rằng nếu ứng dụng được đóng vào thời điểm này (hoặc với nút chéo và Application.Exit()) thì quá trình này sẽ giữ cho zombie mãi mãi.Backgroundworker hủy bỏ

Tôi cần một cách để buộc hủy hoặc hủy chuỗi chủ đề nền.

Trả lời

2

Tôi không chắc chắn về những gì bạn đang cố gắng hoàn thành, nhưng có lẽ sự kiện SerialPort.DataReceived là giải pháp tốt hơn?

Nếu bạn đã thành thạo với việc sử dụng chuỗi, tôi không thấy điểm khi sử dụng Trình tạo nền. Nó được thiết kế cho những người không hiểu chủ đề ở nơi đầu tiên.

Bên cạnh đó, tôi không thích ý tưởng hủy một chuỗi. Nó cảm thấy nguy hiểm, và các ứng dụng đa luồng không cần thêm bất kỳ rủi ro nào.

+0

tôi đã tìm thấy SerialPort.DataReceived là một chút bối rối trong CF, không biết nếu impl là tốt hơn trong FF. Một CF sử dụng nhiều chủ đề hơn bạn mong đợi để xem ra. – Quibblesome

+10

Hầu như bị cám dỗ với -1 cho nhận xét về BackgroundWorker; nó được thiết kế để thực thi một số tiêu chuẩn và các sự kiện sắp xếp tự động vào luồng giao diện người dùng, đó là các lý do hợp lệ cho việc sử dụng nó; không hiểu luồng sẽ gây ra vấn đề không có vấn đề gì theo cách bạn đi. –

+0

Trừ khi có một cách dễ dàng hơn để đồng bộ hóa với chuỗi giao diện người dùng từ một chuỗi bình thường ... – Glimpse

2

Tôi không nghĩ rằng BackgroundWorker hỗ trợ tiêu diệt chuỗi. Việc hủy một thao tác phải được thực hiện theo phương thức thực hiện công việc. Trong trường hợp của bạn, tôi nghĩ rằng một chủ đề thường xuyên sẽ là lựa chọn tốt nhất.

3

Quy trình không được trở thành zombie, vì chuỗi Chủ đề được đánh dấu là "nền" và sẽ kết thúc khi giao diện người dùng bị đóng.

+0

Đó là sự thật vì BW đang sử dụng lớp ThreadPool đằng sau hậu trường. –

5

Tôi đặt cùng nhau (tôi nghĩ) thực hiện công việc. Xin vui lòng cho tôi biết nếu im waaaay off. Dưới đây là một exaple đơn giản như thế nào nó hoạt động.

var backgroundWorker = new BackgroundWorker(){WorkerSupportsCancellation = true}; 

backgroundWorker.DoWork += (sender, args) => 
     {     
       var thisWorker = sender as BackgroundWorker; 
       var _child = new Thread(() => 
               { 
                //..Do Some Code 

               }); 
       _child .Start(); 
       while (_child.IsAlive) 
       { 
        if (thisWorker.CancellationPending) 
        { 
         _child.Abort(); 
         args.Cancel = true; 
        } 
        Thread.SpinWait(1); 
       }     
     }; 

backgroundWorker.RunWorkerAsync(parameter); 
//..Do Something... 
backgroundWorker.CancelAsync(); 

Vì công nhân nền là một phần của nhóm chủ đề, chúng tôi không muốn hủy bỏ nó. Nhưng chúng ta có thể chạy một chuỗi nội bộ mà chúng ta có thể cho phép một sự hủy bỏ xảy ra. BackgroundWorker sau đó về cơ bản chạy cho đến khi một trong hai chủ đề con hoàn thành hoặc chúng tôi báo hiệu cho nó để giết quá trình. Chuỗi công nhân nền sau đó có thể quay trở lại nhóm đọc. Thông thường tôi sẽ quấn nó lên trong một lớp trợ giúp và chuyển qua phương thức ủy nhiệm mà tôi muốn luồng nền chạy qua như tham số và chạy nó trong chuỗi con.

Hãy cho ai đó biết nếu tôi đập đầu vào tường nhưng nó có vẻ hoạt động tốt .. Nhưng đó là vấn đề với chủ đề không phải là .. các kết quả khác nhau bạn có thể nhận được khi bạn chạy nó vào các thời điểm khác nhau.

+0

Đây là một giải pháp thú vị, nhưng trong ý kiến ​​của tôi, nó sẽ hiệu quả hơn khi tạo một lớp bao bọc đối tượng Thread và tương tác với nó, và không sử dụng một BackgroundWorker làm người trung gian. Có thực sự không có lý do cho nó như xa như tôi có thể nhìn thấy. –

0

Bạn có thể thử này:

  backgroundworker.Dispose(); 
      backgroundworker = null; 
      GC.Collect(); //this helps cleans up ram 
Các vấn đề liên quan