2009-05-30 45 views
0



我有一個方法,我想一遍又一遍地運行。c#方法循環和控制

我一直在使用這種模式的一些插座工作,我想知道我可以做什麼改進?

public delegate void VoidMethod(); 

public class MethodLooper 
{ 
    private VoidMethod methodToLoop; 
    private volatile bool doMethod; 
    private readonly object locker = new object(); 
    private readonly Thread loopingThread; 

    public void Start() 
    { 
     if (!doMethod) 
     { 
      doMethod = true; 
      loopingThread.Start(); 
     } 
    } 

    public void Stop() 
    { 
     if (doMethod) 
     { 
      doMethod = false; 
      loopingThread.Join(); 
     } 
    } 

    public void ChangeMethod(VoidMethod voidMethod) 
    { 

     if (voidMethod == null) 
      throw new NullReferenceException("voidMethod can't be a null"); 

     Stop(); 
     lock (locker) 
     { 
      methodToLoop = voidMethod; 
     } 
    } 

    public MethodLooper(VoidMethod voidMethod) 
    { 
     if (voidMethod == null) 
      throw new NullReferenceException("voidMethod can't be a null"); 
     methodToLoop = voidMethod; 
     loopingThread = new Thread(new ThreadStart(_MethodLoop)); 
    } 

    private void _MethodLoop() 
    { 
     VoidMethod methodToLoopCopy; 
     while (doMethod) 
     { 
      lock (methodToLoop) 
      { 
       methodToLoopCopy = methodToLoop; 
      } 
      methodToLoopCopy(); 
     } 
    } 
} 
+0

對不起!錯誤修正abelenky - 即時累了 - 現在穩定與獵戶座建議的一些功能 – divinci 2009-05-31 02:07:32

回答

1

一個更安全的版本會做這樣的:

private readonly object m_locker = new object(); // readonly so it can never be null 
private readonly Thread m_workerThread; // readonly so must set in constructor, 
    // and never can be null afterwards 

private Action m_methodToRun; 
private volatile bool m_keepGoing = true; // needs to be volatile or else you need to lock around accesses to it. 

public Constructor() 
{ 
    m_workerThread = new Thread(ThreadWorker); 
} 

public void SetMethod(Action action) 
{ 
    lock(m_locker) 
    m_methodToRun = action; 
} 

private void ThreadWorker() 
{ 
    while(m_keepGoing) 
    { 
    // use a lock to take a local copy in case another thread sets m_methodToRun to null 
    // while we are processing things 
    Action methodLocal; 
    lock(m_locker) 
     methodLocal = m_methodToRun; 

    methodLocal(); // call it 
    // Note: Remember that the underlying method being pointed to must ALSO be 
    // thread safe. Nothing you do here can make up for that if it is not. 
    } 
} 

private void Stop() 
{ 
    m_keepGoing = false; 
    m_workerThread.Join(); // BLOCK and wait for it to finish 
} 

private void Start() 
{ 
    m_keepGoing = true; 
    m_workerThread.Start(); 
} 

this other question的細微之處揮發性VS鎖定

1

那麼你應該將doMethodToLoop表示爲volatile。如MSDN中所述:

「volatile關鍵字表示可以通過某些操作系統,硬件或併發執行的線程等方式在程序中修改某個字段。」

我很着急,但您應該查看this tutorial從開關的代碼。

+0

@Cris - 好點 - 虐待編輯。 – divinci 2009-05-31 00:06:40

+0

是的 - 沒有易失性是如果您切換到CPU架構(例如Itanium)就會咬你的東西。 – RichardOD 2009-05-31 15:46:01