2010-06-17 20 views
6

Hãy nói rằng tôi có một nền công nhân như thế này:Làm thế nào để bắt đầu và ngừng Một Liên tục chạy Worker nền Sử dụng Button A

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      while(true) 
      { 
        //Kill zombies 
      } 
     } 

Làm thế nào tôi có thể làm cho nền tảng này người lao động bắt đầu và ngừng sử dụng một nút trên một WinForm?

+3

Hmm, cho câu trả lời bạn được chấp nhận, hãy cẩn thận - bạn đang lo lắng tất cả về ảnh hưởng đó sẽ chỉ gây ra nó không dừng lại một lần lặp hoặc hai sau đó, nhưng quên rằng bạn sẽ BẮT BUỘC lên một bộ vi xử lý toàn bộ chỉ cần quay! Ít nhất hãy ngủ trong đó. Nó sẽ có vẻ như nó hoạt động nhưng gây thiệt hại lớn.Một số câu trả lời khác giải quyết tất cả những vấn đề đó theo cách mà bạn đang 'giả sử' để giải quyết chúng. – FastAl

Trả lời

5
+0

Hoạt động tốt: D – sooprise

+0

"Truy cập và cập nhật một bool là một hoạt động nguyên tử". Đây có phải là do rào cản bộ nhớ? –

+0

Không, nguyên tử có nghĩa là giá trị đúng hoặc sai sẽ được viết bằng một lần. Một rào cản bộ nhớ quy định thứ tự viết hoặc đọc của giá trị được xem bởi một luồng khác. Không có gì nói rằng giá trị được viết cho _performKilling sẽ không bao giờ được hiển thị trong một chuỗi khác mà không có cơ chế như vậy. Nguyên tử có nghĩa là giá trị được đọc sẽ luôn đúng hoặc sai, điều đó không có nghĩa là chuỗi nền sẽ từng thấy giá trị được viết gần đây nhất. –

0

tôi đã không kiểm tra này, tôi có mã đâu đó rằng tôi sẽ phải xem chính xác những gì tôi đã làm, nhưng một cái gì đó như thế này là một sự thích nghi của câu trả lời Fredrik của:

private bool _performKilling; 
private object _lockObject = new object(); 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    while(true) 
    { 

     if (_performKilling) 
     { 
      //Kill zombies 
     } 
     else 
     { //We pause until we are woken up so as not to consume cycles 
      Monitor.Wait(_lockObject); 
     } 
    } 
} 

private void StartKilling() 
{ 
    _performKilling = true; 
    Monitor.Pulse(_lockObject); 
} 

private void StopAllThatKilling() 
{ 
    _performKilling = false; 
] 

ví dụ hoàn chỉnh hơn về mô hình này ở đây:

https://github.com/AaronLS/CellularAutomataAsNeuralNetwork/blob/fe9e6b950e5e28d2c99350cb8ff3157720555e14/CellLifeGame1/Modeling.cs

+0

Ah, tất nhiên; giải pháp tốt đẹp. Tôi phải mệt mỏi khi không tự mình bắt đầu với nó;) –

+0

_ "Tôi chưa thử nghiệm điều này" _ - rõ ràng, vì các cuộc gọi đến 'Wait()' và 'Pulse()' sẽ ném ngoại lệ, bởi vì bạn đã không lấy màn hình trước khi gọi những phương pháp đó. –

+0

@PeterDuniho Tất nhiên có một số hệ thống ống nước không được hiển thị ở đây. Chỉ có nghĩa là nên sử dụng một vài phương pháp trên Màn hình để tạo điều kiện tạm dừng/bỏ tạm dừng. Ví dụ hoàn chỉnh hơn ở đây: https://github.com/AaronLS/CellularAutomataAsNeuralNetwork/blob/fe9e6b950e5e28d2c99350cb8ff3157720555e14/CellLifeGame1/Modeling.cs – AaronLS

17

lẽ bạn có thể sử dụng một ManualResetEvent như thế này, tôi di không gỡ lỗi này nhưng giá trị một shot. Nếu nó hoạt động, bạn sẽ không có chủ đề quay bánh xe của nó trong khi chờ đợi

ManualResetEvent run = new ManualResetEvent(true); 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    while(run.WaitOne()) 
    { 
     //Kill zombies 
    } 
} 

private void War() 
{ 
    run.Set(); 
} 

private void Peace() 
{ 
    run.Reset(); 
} 
+0

+1 Thật tuyệt vời khi thấy một linh hồn khác thực sự hiểu được luồng .NET. ;) Tôi nghĩ việc sử dụng WaitHandle luôn là lựa chọn tốt hơn trong những tình huống này, vì chúng thực sự quan tâm đến nguyên tử và các vấn đề đa luồng khác cho bạn (giả sử bạn chọn đúng loại WaitHandle). – jrista

+0

'while (true) {if (run.WaitOne()) {}}'? Có vẻ hơi dư thừa, phải không? Tại sao không 'while (run.WaitOne()) {}'? –

+0

Nó thực sự là, tôi nghĩ rằng bản thân mình sau khi gửi bài, tôi sẽ cập nhật nó –

7

Sử dụng phương pháp CancelAsync.

backgroundworker1.CancelAsync(); 

Trong vòng lặp của bạn bên trong chuỗi công nhân.

if (backgroundWorker.CancellationPending) return; 

Điều này không xảy ra ngay lập tức.

+5

+1: Tôi không hiểu tại sao mọi người lại nói 'while (_someCustomBoolean) 'khi lớp' BackgroundWorker' đã có sẵn chức năng này. –

+1

Sau khi hủy chờ xử lý được đặt, tôi nghĩ giao thức chung là để nhân viên nền dừng và hoàn tất. Trong tình huống này, tôi tin rằng các câu hỏi đã yêu cầu một cách để bắt đầu và dừng lại. Nhân viên nền cũng có thể đi cùng bạn. Nếu bạn sử dụng sự kiện chưa hoàn thành của nó, điều này được đăng thông qua .net chung ThreadPool, tôi đã thấy bế tắc này trước khi tùy thuộc vào những gì khác được ném trên đó. –

4

Bằng cách dừng lại, bạn có thực sự muốn dừng hoặc bạn có nghĩa là tạm dừng không? Nếu bạn muốn dừng lại, thì đây là một miếng bánh. Tạo nút xử lý sự kiện nhấn nút cho nút bạn muốn chịu trách nhiệm khởi động công nhân nền và trình xử lý sự kiện nhấn nút cho người chịu trách nhiệm dừng nó. Trên nút bắt đầu của bạn, thực hiện cuộc gọi đến phương thức nhân viên nền để kích hoạt sự kiện do_work. Một cái gì đó như thế này:

private void startButton_Click(System.Object sender, 
    System.EventArgs e) 
{ 
    // Start the asynchronous operation. 
    backgroundWorker1.RunWorkerAsync(); 
} 

Mở nút dừng của bạn, thực hiện cuộc gọi đến các phương pháp mà bộ công nhân nền của CancellationPending true, như thế này:

private void cancelAsyncButton_Click(System.Object sender, 
    System.EventArgs e) 
{ 
    // Cancel the asynchronous operation. 
    this.backgroundWorker1.CancelAsync(); 
} 

Bây giờ đừng quên để kiểm tra sự CancelationPending cờ bên trong doWork của nhân viên nền của bạn. Một cái gì đó như thế này:

private void KillZombies(BackgroundWorker worker, DoWorkEventArgs e) 
    { 
     while (true) 
     { 
      if (worker.CancellationPending) 
      { 
       e.Cancel = true; 
      } 
     } 
    } 

Và phương pháp DoWork của bạn:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      BackgroundWorker worker = sender as BackgroundWorker; 
      KillZombies(worker, e); 
     } 

Tôi hy vọng điều này có thể hướng bạn đi đúng hướng. Một số bài đọc thêm:

http://msdn.microsoft.com/en-us/library/b2zk6580(v=VS.90).aspx

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

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

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