사용하려는 System.Timers.Timer 개체가 있지만 Timer에 연결된 처리를 높은 우선 순위의 스레드에 정상적으로 간섭하지 않으려합니다. 다른 말로하면 나는 아무 것도 실행하지 않는 한 X를 5 초마다 처리하려고한다고 말하고 싶습니다..Timer Elapsed 이벤트는 High Priority 스레드와 어떻게 경쟁합니까?
Timer 작업이 우선 순위가 낮은 방식으로 실행되도록하려면 어떻게해야합니까?
사용하려는 System.Timers.Timer 개체가 있지만 Timer에 연결된 처리를 높은 우선 순위의 스레드에 정상적으로 간섭하지 않으려합니다. 다른 말로하면 나는 아무 것도 실행하지 않는 한 X를 5 초마다 처리하려고한다고 말하고 싶습니다..Timer Elapsed 이벤트는 High Priority 스레드와 어떻게 경쟁합니까?
Timer 작업이 우선 순위가 낮은 방식으로 실행되도록하려면 어떻게해야합니까?
System.Timers.Timer에 대한 좋은 점은 SynchronizingObject
속성을 통해 동기화 객체를 할당 한 다음이 객체를 악용하여 Elapsed
이벤트를 실행하여 우선 순위를 제어 할 수 있다는 것입니다.
타이머의 SynchronizingObject
속성에 ElapsedEventReceiver
의 인스턴스를 할당하기 만하면됩니다.
면책 조항 : 나는 이것을 아주 빨리 처리 했으므로 마무리 작업을 추가해야 더욱 강력 해졌습니다.
public class ElapsedEventReceiver : ISynchronizeInvoke
{
private Thread m_Thread;
private BlockingCollection<Message> m_Queue = new BlockingCollection<Message>();
public ElapsedEventReceiver()
{
m_Thread = new Thread(Run);
m_Thread.Priority = ThreadPriority.BelowNormal;
m_Thread.IsBackground = true;
m_Thread.Start();
}
private void Run()
{
while (true)
{
Message message = m_Queue.Take();
message.Return = message.Method.DynamicInvoke(message.Args);
message.Finished.Set();
}
}
public IAsyncResult BeginInvoke(Delegate method, object[] args)
{
Message message = new Message();
message.Method = method;
message.Args = args;
m_Queue.Add(message);
return message;
}
public object EndInvoke(IAsyncResult result)
{
Message message = result as Message;
if (message != null)
{
message.Finished.WaitOne();
return message.Return;
}
throw new ArgumentException("result");
}
public object Invoke(Delegate method, object[] args)
{
Message message = new Message();
message.Method = method;
message.Args = args;
m_Queue.Add(message);
message.Finished.WaitOne();
return message.Return;
}
public bool InvokeRequired
{
get { return Thread.CurrentThread != m_Thread; }
}
private class Message : IAsyncResult
{
public Delegate Method;
public object[] Args;
public object Return;
public object State;
public ManualResetEvent Finished = new ManualResetEvent(false);
public object AsyncState
{
get { return State; }
}
public WaitHandle AsyncWaitHandle
{
get { return Finished; }
}
public bool CompletedSynchronously
{
get { return false; }
}
public bool IsCompleted
{
get { return Finished.WaitOne(0); }
}
}
}
아마도 가장 쉬운 방법은 '사용중'플래그 (또는 카운트)를 사용하는 것이고 0이 아닌 한 타이머 틱을 무시하는 것입니다.
P. 스레드 우선 순위 변경은 권장되지 않습니다. 거의 필요하지 않습니다.
내 응용 프로그램이 서버의 다른 응용 프로그램에 영향을 미치지 않는지 확인하십시오. 나는 프로파일 링 애플리케이션을 작성하고있다. –
다른 응용 프로그램의 스레드 우선 순위를 변경하는 것은 비현실적 일 수 있지만 자신의 응용 프로그램 우선 순위를 낮추는 것은 거의 불가능합니다. @Michael Hedgpeth - 그러나 프로파일 링 응용 프로그램은 아마도 반대 사례입니다! –
@ 제프리 : 나는 동의하지 않는다. 스레드의 정확한 우선 순위는 반 직관적이며 동적 우선 순위가 Windows 스케줄러에 내장되어 있기 때문에 스레드 우선 순위를 수동으로 조정하면 종종 비생산적입니다. –
이 대답이 주소 지정없이 가정하는 중요한 정보 중 하나는 Windows에서 우선 순위가 더 높은 스레드를 실행할 수있는 한 (일반적으로) 더 낮은 우선 순위의 스레드가 실행되도록 예약되지 않는다는 사실입니다. 즉, 스레드의 priorty를 설정하면 원하는 것을 얻을 수 있습니다. 이 사실은 일부 사람들이 타임리스트의 크기 또는 다른 스키마 만 조정한다고 가정 할 수도 있기 때문에 분명하지 않을 수 있습니다. Windows는 잠시 동안 실행되지 않는 경우 우선 순위가 낮은 스레드를 "굶주 리지"않겠지 만 실제로는 문제가되지는 않습니다. –
@ 제프리 : 좋은 지적입니다. 실 제로는 현재 예제에서 실제로 문제가 될 수 있습니다. 왜냐하면 실행을 위해 정렬 된 메시지가 대기열을 쌓아 쌓기 시작할 것이기 때문입니다. 나는 기회가있을 때 이것을 수정하려고 노력할 것이다. –