첫째, .NET에서/기본 클래스 라이브러리는, 그것의 콜백 코드가 올바른 스레드에서 실행되도록 일반적으로 이벤트 가입자의 의무이므로주의하시기 바랍니다. 이벤트 제작자가 쉽게 만들 수 있습니다. 다양한 구독자의 스레드 유사성에 신경 쓰지 않고 이벤트를 트리거 할 수 있습니다.
가능한 구현의 단계별 설명은 다음과 같습니다.
간단한 설명부터 시작하겠습니다. Producer
클래스 및 해당 이벤트는 Event
입니다. 내 예는 어떻게이 이벤트가 트리거됩니다 때 포함되지 않습니다 :
class Producer
{
public event EventHandler Event; // raised e.g. with `Event(this, EventArgs.Empty);`
}
다음으로, 우리는이 이벤트에 우리 Consumer
인스턴스를 구독하고 다시 특정 스레드에서 호출 할 수 있어야합니다 (I이 전화 할게 스레드 종류 "작업자 스레드") :
class Consumer
{
public void SubscribeToEventOf(Producer producer, WorkerThread targetWorkerThread) {…}
}
어떻게 구현하나요?
먼저 특정 작업자 스레드에 코드를 "전송"해야합니다. 원할 때마다 스레드가 특정 메소드를 실행하도록 할 수있는 방법이 없으므로 명시 적으로 작업 항목을 대기하도록 작업자 스레드를 정렬해야합니다. 이를 수행하는 한 가지 방법은 작업 항목 큐를 사용하는 것입니다.
sealed class WorkerThread
{
public WorkerThread()
{
this.workItems = new Queue<Action>();
this.workItemAvailable = new AutoResetEvent(initialState: false);
new Thread(ProcessWorkItems) { IsBackground = true }.Start();
}
readonly Queue<Action> workItems;
readonly AutoResetEvent workItemAvailable;
public void QueueWorkItem(Action workItem)
{
lock (workItems) // this is not extensively tested btw.
{
workItems.Enqueue(workItem);
}
workItemAvailable.Set();
}
void ProcessWorkItems()
{
for (;;)
{
workItemAvailable.WaitOne();
Action workItem;
lock (workItems) // dito, not extensively tested.
{
workItem = workItems.Dequeue();
if (workItems.Count > 0) workItemAvailable.Set();
}
workItem.Invoke();
}
}
}
이 클래스는 기본적으로 스레드를 시작하고, 항목이 큐 (workItems
)에 도착할 때까지 잠 (WaitOne
) 폭포 무한 루프에 넣습니다 : 여기 WorkerThread
에 대한 가능한 구현이다. 그런 일이 발생하면 — Action
— 항목이 대기열에서 제외되고 호출됩니다. 그런 다음 스레드는 대기열에서 다른 항목을 사용할 수있을 때까지 다시 잠자기 상태가됩니다 (WaitOne
).
Action
은 QueueWorkItem
메서드를 통해 대기열에 저장됩니다. 그래서 본질적으로 우리는 이제 해당 메소드를 호출하여 특정 WorkerThread
인스턴스로 실행될 코드를 보낼 수 있습니다. 이제 구현할 준비가되었습니다. Customer.SubscribeToEventOf
:
class Consumer
{
public void SubscribeToEventOf(Producer producer, WorkerThread targetWorkerThread)
{
producer.Event += delegate(object sender, EventArgs e)
{
targetWorkerThread.QueueWorkItem(() => OnEvent(sender, e));
};
}
protected virtual void OnEvent(object sender, EventArgs e)
{
// this code is executed on the worker thread(s) passed to `Subscribe…`.
}
}
Voilà!
P.S. (자세히 설명하지 않음) :
sealed class WorkerThreadSynchronizationContext : SynchronizationContext
{
public WorkerThreadSynchronizationContext(WorkerThread workerThread)
{
this.workerThread = workerThread;
}
private readonly WorkerThread workerThread;
public override void Post(SendOrPostCallback d, object state)
{
workerThread.QueueWorkItem(() => d(state));
}
// other overrides for `Send` etc. omitted
}
그리고 WorkerThread.ProcessWorkItems
의 시작, 당신이 '추가 기능, 당신은 표준 .NET 메커니즘이 SynchronizationContext
라고 사용 WorkerThread
에 코드를 전송하는 방법을 포장 수로 다음과 같이 특정 스레드에 대한 동기화 컨텍스트를 설정 D :
SynchronizationContext.SetSynchronizationContext(
new WorkerThreadSynchronizationContext(this));
당신은 할 수 있지만 [실제 문제를 해결하기의 더 나은 방법이있을 수있다 (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). 이 이벤트 시스템을 사용하여 해결하려는 것을 설명 할 수 있습니까? –
추가 확장이 필요한 경우 알려 주셔서 감사합니다. – Mehran
훨씬 더 나은, 나는 그것을 해결하는 방법을 잘 모르겠지만 지금 당신의 문제가 무엇인지 이해합니다. –