C# 메소드 루핑 및 제어
-
06-09-2019 - |
문제
나는 계속해서 달리기하고 싶은 방법이 있습니다.이 과정을 시작하고 중지하고 싶습니다.
소켓 작업 에이 패턴을 사용해 왔으며 어떤 개선을 할 수 있는지 궁금합니다.
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에 언급 된 바와 같이 :
"휘발성 키워드는 운영 체제, 하드웨어 또는 동시에 실행되는 스레드와 같이 프로그램에서 필드를 프로그램에서 수정할 수 있음을 나타냅니다."
나는 서두르지 만 당신은 체크 아웃해야합니다 이 튜토리얼 코드의 스위치에서.
제휴하지 않습니다 StackOverflow