2009-07-30 27 views
6

Tôi cần phải thông báo một chuỗi công nhân được gọi là ngừng hoạt động ở tính khả thi tiếp theo. Hiện tại tôi đang sử dụng một cái gì đó như thế này:Các tùy chọn để thông báo cho một Chủ đề dừng lại

public void Run() 
    { 
     while (!StopRequested) 
      DoWork(); 
    } 

Tôi lo ngại rằng StopRequested đang được đặt thành True trên một chuỗi khác. Điều này có an toàn không? Tôi biết tôi không thể khóa một boolean. Có lẽ có một cách khác nhau để thông báo cho một sợi rằng dừng là bắt buộc. Ví dụ tôi sẽ rất vui khi kiểm tra Thread.CurrentThread.ThreadState == ThreadState.StopRequested nhưng không rõ làm thế nào tôi có thể thiết lập trạng thái luồng như vậy.

+0

Tại sao bạn không thể khóa xung quanh một boolean? Nó thường được coi là thực hành tốt để tạo ra một 'Object' riêng biệt cho bất kỳ ổ khóa, dù sao đi nữa. –

+0

Tôi không thể khóa bool vì 'một loại giá trị - tôi có thể tạo ra một đối tượng đồng bộ được gọi là không có mục đích khác hơn là khóa nó khi nhận/thiết lập cờ bool --- nhưng dường như với tôi trên một bool nên được an toàn, và ít nhất Reed Copsey đồng ý –

+0

Vâng, khóa xung quanh một bool nên được an toàn. Hủy hợp tác. Backgroundworker hỗ trợ một khái niệm tương tự nếu nó phù hợp với nhiệm vụ bạn đang thực hiện. –

Trả lời

3

Đây là cách tiếp cận tốt hơn là cố gắng đặt ThreadState. Nếu bạn nhìn vào các tài liệu cho ThreadState, nó đặc biệt nói rằng StopRequested chỉ dành cho sử dụng nội bộ.

Đặt boolean từ chuỗi khác là thao tác an toàn. Bạn không cần phải khóa trong trường hợp này.

+0

Tôi muốn đọc thêm về phương pháp này. Bạn có liên kết đến các câu hỏi, giấy tờ, blog tương tự không? –

2

Sử dụng đối tượng Sự kiện sẽ có thể tốt hơn. Đặc biệt là nếu khối chuỗi của bạn. (Sau đó, bạn vẫn có thể đợi sự kiện bên trong cuộc gọi chặn)

3

Bạn có thể muốn xem bằng cách sử dụng BackgroundWorker để thực hiện công việc cho bạn, sử dụng RunWorkerAsync() và xử lý trường hợp worker.CancellationPending == true trong quá trình logic của bạn.

BackgroundWorker worker = new BackgroundWorker(); 
worker.WorkerSupportsCancellation = true; 
worker.DoWork += MyWorkFunction; 
worker.RunWorkerCompleted += MyWorkDoneSuccessfullyFunction; 
worker.RunWorkerAsync(); 

Một giải pháp khác là sử dụng một bool dễ bay hơi để báo hiệu rằng bạn cần dừng lại, bạn có thể đặt bất kỳ vị trí nào trong lớp.

private volatile bool cancelWork = false; 

public void CancelWork() 
{ 
    cancelWork = true; 
} 
+0

e.Cancelled chỉ sau khi nhân viên đã bị ngừng, xem bài đăng của tôi dưới đây – SwDevMan81

+0

@ SwDevMan81: Bạn đã chính xác, đã chỉnh sửa nhận xét đó.Việc triển khai chính xác cho DoWork có thể tìm thấy tại đây: http://msdn.microsoft.com/en-us/library/system.componentmodel.doworkeventargs.argument.aspx –

2

Bạn có thể sử dụng Thread.Abort() và bọc bất kỳ dọn dẹp cần thiết nào trong phương thức DoWork() trong một khối cuối cùng.

0

Nếu bạn sử dụng BackgroundWorker, bạn sẽ gọi CancelAsync chức năng của BackgroundWorker đặt CancellationPending tài sản là true, đó là những gì bạn sẽ tìm kiếm trong vòng lặp của bạn:

public void Run(object sender, DoWorkEventArgs e) 
{  
    BackgroundWorker worker = sender as BackgroundWorker; 
    if(worker != null) 
    { 
     while (!worker.CancellationPending) 
     { 
     DoWork(); 
     } 
    } 
} 

Trên đây sẽ là DoWork mã sự kiện được gọi khi bạn chạy hàm RunWorkerAsync.

1

Mối quan tâm tôi có là StopRequested đang được đặt thành True trên một luồng khác. Điều này có an toàn không?

Bạn nên đảm bảo rằng trường StopRequested có từ khóa volatile. Xem this other answer vì lý do tại sao.

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