문제



나는 계속해서 달리기하고 싶은 방법이 있습니다.이 과정을 시작하고 중지하고 싶습니다.

소켓 작업 에이 패턴을 사용해 왔으며 어떤 개선을 할 수 있는지 궁금합니다.

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();
        }
    }
}
도움이 되었습니까?

해결책

더 안전한 버전은 다음과 같이하는 것입니다.

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();
}

보다 이 다른 질문 휘발성 대 잠금의 더 미세한 점

다른 팁

글쎄, 당신은 domethodtoloop을 휘발성으로 표현해야합니다. MSDN에 언급 된 바와 같이 :

"휘발성 키워드는 운영 체제, 하드웨어 또는 동시에 실행되는 스레드와 같이 프로그램에서 필드를 프로그램에서 수정할 수 있음을 나타냅니다."

나는 서두르지 만 당신은 체크 아웃해야합니다 이 튜토리얼 코드의 스위치에서.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top