2009-03-12 1 views
1

나는 게으르다 (때로는 좋을 것이다) InvokeRequired을 먼저 검사하지 않고 콜백을 호출하여 WinForms UI를 업데이트하기 시작했다.먼저 InvokeRequired를 확인하지 않고 UI를 업데이트 할 때 성능 문제가 있습니까?

알고 있어야하는 성능 문제 또는 고려 사항이 있습니까?

private delegate void SetStatusEventHandler(string statusMessage); 
    private void SetStatus(string statusMessage) 
    { 
     Invoke((MethodInvoker) (() => 
     { 
      resultLabel.Text = statusMessage; 
     })); 

     // - vs - 

     if (InvokeRequired) 
     { 
      SetStatusEventHandler cb = SetStatus; 
      Invoke(cb, statusMessage); 
     } 
     else 
     { 
      resultLabel.Text = statusMessage; 
     } 
    } 

는 [편집] : 가장 좋아에서 호출하는 방법은 "호출"라는 시간의 대부분이라고한다은 해당 증속 넓은 간격으로 10 ~ 20 회 두 번째 말한다.

[업데이트] 내가 확장 메서드 클래스를 관리하는 방법을 알아내는 추측 다음 확장 메서드

public static class SmartInvoker 
{ 
    public static void InvokeHandler(this Control control, MethodInvoker del) 
    { 
     if (control.InvokeRequired) 
     { 
      control.Invoke(del); 
      return; 
     } 
     del(); 
    } 
} 

... 

    private void SetStatus(string statusMessage) 
    { 
     this.InvokeHandler(() => resultLabel.Text = statusMessage); 
    } 

으로 정착 내가 발굴해야 할 또 다른 주제는 . 당신의 도움

주셔서 감사합니다

답변

3

편집 : 전체 게시와 말라키 즉시 발송에 대한 토론에 대한 의견을 참조하십시오.

내 대답은 실제로 동일합니다. 이런 일이 발생하지 않는 한 매우 불규칙한 경우가 종종 있습니다 (예 : UI 스레드에서 시작하는 대부분의 시간이며 마우스 이동 핸들러) 나는 걱정하지 않을 것이다. 확실히 코드가 간단 해집니다. 이 매우 자주 호출 할 것입니다, 내가 측정하는 것보다 테스트 :

Invoke가 빠를 EventHandler 또는 MethodInvoker 대표와 다른 사람에 비해입니다. 나는 둘 사이에 어떤 차이가 있는지 모르겠다 - 당신은 점검하고 싶을지도 모른다.

확장 메소드를 작성하여이 작업을 훨씬 간단하게 만들 수 있습니다.

public static void InvokeHandler(this Control control, MethodInvoker handler) 
{ 
    control.Invoke(handler); 
} 

그럼 당신은 당신의 코드를 만들 수 있습니다

private void SetStatus(string statusMessage) 
{ 
    this.InvokeHandler(delegate 
    { 
     resultLabel.Text = statusMessage; 
    }); 
} 

또는

private void SetStatus(string statusMessage) 
{ 
    InvokeHandler(() => resultLabel.Text = statusMessage); 
} 

당신이 대리자 형식을 지정하지 않아도 그런 식으로.

+0

나는 생각하지 않았다.나는 이벤트 큐를 포함하지 않고 * 호출 만한다는 인상을 받았다. –

+0

@Marc, 나는 리플렉터 코드를 간단히 들여다 보았다. 그리고 invoke가 항상 이벤트 큐를 통과하는 것처럼 보인다. 그래도 깊은 수사는하지 않았다. – JaredPar

+0

아니요, 동일한 Control.MarshaledInvoke 코드 경로를 통과합니다. 큐에 배치하지만 큐를 즉시 실행합니다. –

3

확장 메소드를 추가하지 않고 더 이상 생각할 필요가없는 이유는 무엇입니까?

public static object SmartInvoke(this Control control, MethodInvoker del) { 
    if (control.InvokeRequired) { 
    control.Invoke(del); 
    return; 
    } 
    del(); 
} 

이제 코드는

private void SetStatus(string statusMessage) { 
    this.SmartInvoke(() => resultLabel.Text = statusMessage); 
} 
+0

당신이 컨트롤 자체 내에 있다면 SmartInvoke 전에 이것을 필요로합니다. this.SmartInvoke (...); – Samuel

+0

@ Samuel, "this"는이 경우에 불필요합니다. – JaredPar

+0

확장 메서드 사용을 고려해야하는지 잘 모르겠습니다. 확장 메서드를 사용하는 것이 좋은 아이디어인지 아닌지 먼저 조사하고 싶습니다. 그러나 이것은 나의 문제를 다루는 꽤 게으른 길처럼 들린다. @JaredPar, – Sung

0

난 당신이 동일한 스레드에서 이미 있다면 그냥 불필요한 게시물을 방지 생각된다. 그래서 그게 가장 일반적인 시나리오 (올바른 스레드에) 될 것이라고, 그것은 작은 성능에 치여서 검사를하지 않을 수도 있지만, 그게 실제로 필요하다고 생각하지 않습니다.

관련 문제