2010-02-12 46 views
2

我做了一些研究,并环顾四周,似乎要做到这一点的方法是使用AutoResetEvent。我很快把它放在一起,它似乎工作,似乎是线程安全的。我可以有一些反馈吗?编辑: 嗨,再次。我已经使用了反馈,我对我的实现感到满意。只是我想补充的一件小事,当我暂停时,我想等待确保线程已经暂停并且不再工作。那可能吗?也许我应该只更换暂停和恢复,只有开始和停止,然后停止做一个thred.join()。注释?.Net Thread.Suspend已过时。寻找替代品

+1

我不知道在ContinueProcessing setter中是否会遇到订购问题? – ziya 2010-02-12 12:36:45

+0

你设置_continueProcessing两次 - 锁定和解锁 – tanascius 2010-02-12 12:37:38

+0

也许你应该把所有的锁(在ContinueProcessing setter中)或考虑一种不使用标志的方式? http://dotnet.org.za/markn/archive/2008/10/21/net-memory-model-bytecode-reordering.aspx – ziya 2010-02-12 12:44:52

回答

1

一旦调用exit,ManualResetEvent就会被抛弃,并且在调用时可能会在实例方法上抛出异常。 - >在某些情况下,这可能不是理想的

class Program { 
     static void Main(string[] args) { 

      //NOTE: if worker goes out of scope it will be collected -> ex: promote to field in real use 
      Worker worker = new Worker(); 
      System.Threading.Thread workerThread = new System.Threading.Thread(new System.Threading.ThreadStart(worker.DoWork)); 
      workerThread.IsBackground = true; 
      workerThread.Start(); 

      // test 
      worker.Resume(); 
      System.Threading.Thread.Sleep(2000); 

      worker.Pause(); 
      System.Threading.Thread.Sleep(2000); 

      worker.Resume(); 
      System.Threading.Thread.Sleep(2000); 

      worker.Exit(); 
      System.Threading.Thread.Sleep(5000);   
     } 
    } 

    public class Worker { 

     private readonly System.Threading.ManualResetEvent _Gate; 
     private bool _IsActive; 

     public Worker() { 

      _Gate = new System.Threading.ManualResetEvent(false); 
      _IsActive = true; 
     } 

     public void DoWork() { 

      while (IsActive) { 
       _Gate.WaitOne(); 
       // do work 

       // can yield the thread 
       System.Threading.Thread.Sleep(1); 
      } 

      // dispose 
      _Gate.Close(); 
     } 

     private bool IsActive { 
      get { 
       lock (_Gate) { 
        return _IsActive; 
       } 
      } 
     } 

     public void Pause() { 
      _Gate.Reset(); 
     } 

     public void Resume() { 
      _Gate.Set(); 
     } 

     public void Exit() { 
      lock (_Gate) { 
       _IsActive = false; 
      } 
     } 
    } 
0

看起来过于复杂

public void StopProcessing() 
    { 
     workerThread.Interrupt(); 
     workerThread.Join(); 
    } 

可以,如果你只是让线程退出的方法

0

如果改为使用ManualResetEvent的,你可以删除_continueProcessing变量被删除。在设置中,只需调用事件的Set或Reset。在getter中,你可以返回aResetEvent.WaitOne(0)。然后,您可以在DoSomeProcessing结束时删除一段代码,以便在处理应该持续时设置该事件。另外,因为ManualResetEvent本身是线程安全的,您可以完全删除您的锁定。

关于退出DoSomeProcessing方法。也许最好的办法是使用你设置的标志来告诉循环退出,在循环开始时用锁来测试标志(是的,你现在必须把一些锁定回去),当你想要放弃,您设置标志,然后设置事件。

或者,您可以使用另一个事件来指示循环应该退出并更改您的等待以使用WaitHandle.WaitAny()。