2013-12-12 3 views
0

이벤트에 가입 한 스레드 풀 스레드가 있고 다른 스레드에서 이벤트 처리기가 실행됩니다. 내 질문은 - 언제 스레드 풀 스레드가 다시 풀로 돌아가거나 이벤트 구독이 활성화되어있는 한 주변에 머무를 것입니까? 예를 들어스레드 풀 스레드 및 이벤트 수신 대기

:

public class RunTasks 
    { 
     private readonly MyTask _myTask; 

     public RunTasks(MyTask myTask) 
     { 
      _myTask = myTask; 
     } 

     public void Execute() 
     { 
      ThreadPool.QueueUserWorkItem((ignore) => _myTask.Execute()); 
     } 
    } 

    public class MyTask 
    { 
     private readonly IThridPartyApi _dependency; 

     public MyTask(IThridPartyApi dependency) 
     { 
      _dependency = dependency; 
     } 

     public void Execute() 
     { 
      _dependency.UpdateEvent -= Handler; 
      _dependency.UpdateEvent += Handler; 
     } 

     private void Handler(object sender, EventArgs e) 
     { 
      //raised on another thread as it's coming from a thrid party library. 
     } 
    } 

    public interface IThridPartyApi 
    { 
     event EventHandler<EventArgs> UpdateEvent; 
    } 

위의 예에서 우리는 (100의 범위)를 여러 번 호출되는 이벤트 핸들러가 그 중 50 해고 도착하고 다음 지연되었다 RunTasks.Execute 방법 가정 해 봅시다 50 - 얼마나 많은 활성 스레드가 이벤트 구독을 수신 대기합니까? 내 응용 프로그램 에서이 시나리오를 가지고, 그래서이 구현의 괴물을 만들 아니야 확인하려고합니다. 대답과 이유를 알려주십시오. 또한 이것이 효율적인 구현이 아닌 경우 어떻게 수정합니까 (async를 사용하지 않고도 아직 수정할 수 없음)? Execute 메서드는 UI 단추 처리기에서 시작됩니다.

감사합니다, - 마이크

+0

왜 TPL 대신 자신의 작업을 구현하고 있습니까? 그것은 훨씬 간단한 방법으로 그러한 문제를 해결합니다. 게다가 이벤트 핸들러가 비동기 적으로 실행되기를 원한다면 (예를 들어'async'를 사용하여), 여전히 TPL Tasks를 사용할 필요가 있습니다. –

+0

비동기는 아직 사용하지 않으므로 사용하지 마십시오. 그러나 TPL을 사용할 수는 있지만 어떻게 해결할 수 있습니까? – Mike

+1

코드가 지금과 같은 방식으로 ThreadPool 스레드가 처리기를 설정하고 해제됩니다. 핸들러는 thir-party 스레드에 의해 실행됩니다. 그게 니가 원하는거야? –

답변

0

코드가 지금 보이는 방법, 스레드 풀 스레드가 이벤트 핸들러를 다시 간단하게 사용되며, 다음은 다시 풀에 발표합니다. 이벤트 핸들러는 UpdateEvent 이벤트 (예 : 타사 API의 스레드)를 발생시킨 사람의 스레드에서 실행됩니다.

이 문제를 방지하려면 TaskCompletionSource을 사용하여 이벤트를 작업으로 변환 할 수 있습니다. 자세한 내용은 TPL and Traditional .NET Framework Asynchronous Programming, Exposing Complex EAP operations as Tasks 섹션에 설명되어 있습니다. 이렇게하면 이벤트 핸들러는 ThreadPool 스레드에서 비동기 적으로 실행되며 타사의 스레드는 대기하지 않습니다.

귀하의 경우에는

, 당신은 같은 함수를 만들 수있는 retur 작업 반환하려면 다음

public static Task<object> OnUpdateAsync(this IThridPartyApi dependency) 
{ 
    var tcs=new TaskCompletionSource<object>(); 
    EventHandler handler=null; 
    handler=(obj,args)=> 
    { 
     dependency.UpdateEvent-=handler; 
     //extract the response here 
     tcs.SetResult(response); 
    } 
    dependency.UpdateEvent+=handler; 
    return tcs.Task; 
} 

당신은 당신이 타사 API에서 받으실 무엇 이건 object에서 반환 형식을 변경할 수 있습니다 .