2009-09-08 2 views
3

크로스 스레드 작업을 처리하는 적절한 방법입니까?크로스 스레드 UI 구성 요소 호출

"EditValue"를 재정의하는 대신 "EditValueThreadSafe"와 같은 새 속성 이름을 사용해야합니까? EditValue 구현에 대한 변경 사항에 문제가 있다고 생각하지 않습니다. 기본 속성은 관계없이 호출됩니다.

namespace MyApplication.Components 
{ 
    using System.Windows.Forms; 

    /// <summary> 
    /// Thread-safe implementation of the DevExpress.XtraEditors.ComboBoxEdit class. 
    /// </summary> 
    public class ComboBoxEditThreadSafe : DevExpress.XtraEditors.ComboBoxEdit 
    { 
     /// <summary> 
     /// Gets or sets the edit value. 
     /// </summary> 
     /// <value>The edit value.</value> 
     public override object EditValue 
     { 
      get 
      { 
       return base.EditValue; 
      } 

      set 
      { 
       if (this.InvokeRequired) 
       { 
        this.Invoke(new MethodInvoker(delegate 
        { 
         this.SetEditValue(value); 
        })); 
       } 
       else 
       { 
        this.SetEditValue(value); 
       } 
      } 
     } 

     /// <summary> 
     /// Sets the edit value. 
     /// </summary> 
     /// <param name="value">The value.</param> 
     private void SetEditValue(object value) 
     { 
      base.EditValue = value; 
     } 
    } 
} 

답변

2

또한 잘못된 스레드에서, (BeginInvoke가 true를 반환)하는 경우, 작업을 수행하고, 그 방법에서 다른 방법으로 위임 할 수 있습니다 후 다시 같은 메서드를 호출합니다. 코드를 복제 할 필요가 없습니다.

public class ComboBoxEditThreadSafe : DevExpress.XtraEditors.ComboBoxEdit  
{  
    public override object EditValue   
    {    
     get    
     {        
      return base.EditValue;    
     }    
     set 
     {     
     SetValue(value); 
     } 
    } 



    private void delegate SetValueDlg(object valeu); 
    private void SetValue(object value) 
    { 
     if (this.InvokeRequired) 
      this.BeginInvoke(
       (SetValueDlg)SetValue, // calls itself, but on correct thread 
       new object[] { value }); 
     else 

       base.editValue = value; 

    } 
} 
또한 명시 적으로 위임 클래스를 만들 필요성을 제거하는 작업() 일반적인 클래스를 사용할 수 있습니다

...

public class ComboBoxEditThreadSafe : DevExpress.XtraEditors.ComboBoxEdit  
{  
    public override object EditValue   
    {    
     get { return base.EditValue; }    
     set { SetValue(value); } 
    } 

    private void SetValue(object value) 
    { 
     if (this.InvokeRequired) 
      this.BeginInvoke(
       new Action<object>(SetValue), // calls itself, but on correct thread 
       new object[] { value }); 
     else     
       base.editValue = value; 

    } 

}

+0

무슨 뜻인지 이해가 안됩니다. – Armbrat

+0

아래 내 대답을 참조하십시오. – M1EK

+0

죄송합니다. 잠시 시간을내어 귀하의 재산과 일치하는 코드 스 니펫을 만들었습니다. –

1

그것은 스레드 안전 것은, 그래,하지만 조심해야 속성을 무시하고 근본적으로 동작을 변경합니다. implentation 변경은 괜찮지 만이 속성은 매우 다르게 동작하므로 특정 예외가 발생할 가능성을 없애고 호출 코드에 영향을 줄 수있는 교착 상태 또는 블로킹 상태를 유발할 수 있습니다.

그렇습니다. 이것은 InvokeRequired & Invoke의 올바른 사용법이지만, 광고용으로 별도의 목적 별 및 스레드 안전성 속성을 만드는 것이 좋습니다. 당신이처럼 보이는 끝낼

+0

귀하의 질문에 대한 질문을 확대하십시오. – Armbrat

0

내 UI의 방법처럼 :

public void setStatusLabelText(String s) 
    { 
     if (footerStatusLabel.InvokeRequired) { 
      StringUpdateInvokeDelegate callback = new StringUpdateInvokeDelegate(setStatusLabelText); 
      this.Invoke(callback, new object[] { s }); 
     } 
     else { 
      this.footerStatusLabel.Text = s; 
     }    
    } 

(이 요즘 .NET에 대한 오래된 될 수있다 - 그러나 요점은 당신이 경우에이 방법 내부 작업을 할 만 할 수 있다는 것입니다 이미 올바른 스레드에서 - 읽기 조금 짜증나게하지만, 자바, IMO에 비해 여전히 짜증나게).

+1

파생 된 클래스에서 수행 할 수있을 때 Invoke를 많이 작성하는 것에 지쳤습니다. – Armbrat

0

여기에 2 센트를 주입합니다. InvokeRequired/BeginInvoke/Invoke에 대한 실제 호출은 전적으로 스레드로부터 안전하지 않습니다. (Avoiding the woes of Invoke/BeginInvoke in cross-thread WinForm event handling? 참조) 나는 이것들에 대한 호출을 하나의 장소, 유틸리티 api, 확장 메소드 등에서 분리하는 방법을 찾아 볼 것을 권한다. 위의 문서에는 스레드 안전 동작을 제공하기 위해 대리자를 래핑하는 클래스의 전체 코드가 나와 있습니다.