2011-05-05 5 views
2

다른 스레드에서 업데이트해야하는 컨트롤이 있습니다. Control.Invoke를 사용하면 분명히 가능하지만 최소 10 개의 컨트롤 할당에 대해이 작업을 수행 할 수있는 우아한 방법이 있습니까?Control.Invoke 문제 (x는 필드이지만 메서드처럼 사용됩니다)

또한이 코드의 문제점은 무엇입니까?

InstallationStatus.Invoke(myDelegate = new AssignmentDelegate(InstallationStatus)); 

대리인 내부에서 레이블 (InstallationStatus)의 상태를 설정하고 싶습니다. 대리자가 Control 유형의 인수를 사용하면 오류는 다음과 같습니다.

설치는 필드이지만 메서드처럼 사용됩니다.

감사

+0

은 예에는'Installation' 없다, 그래서 우리는 정말에 대해 언급 할 수 없습니다 "설치가 필드하지만 방법처럼 사용됩니다." –

답변

2

대리인 생성자 호출 할 타겟 방법 허용; 아마 여기에 가장 편리한 방법은 다음과 같습니다

InstallationStatus.Invoke(
     (MethodInvoker) delegate { InstallationStatus = blah; }); 

하지만 다른 변종

+0

정말 고맙습니다. – dotnetdev

0

대안 (및 이럴 구문 조금 더 매력적)이 일의 방법 (공식적인 방법으로 인수로 컨트롤을 전달하는) 존재 이처럼 사용할 수 SynchronizationContext.Send() 경유 :

private System.Threading.SynchronizationContext syncContext; 

public Form1() 
{ 
    InitializeComponent(); 
    syncContext = System.Threading.SynchronizationContext.Current; 
} 

private void UpdateControlsOnTheUIThread() 
{ 
    syncContext.Send(x => 
    { 
     // Do sth here.. 
     myControl.Property = newValue; 
    }, null); 
} 

중요이 적절한 시간에 SynchronizationContext에 인스턴스를 검색 (저장)하는 것입니다. Form의 생성자는 일반적으로 좋은 장소입니다. Send() 메서드에 전달하는 대리자 (또는 익명 메서드) 내에서 여러 컨트롤을 분명히 업데이트 할 수 있습니다.

0

여기 리플렉션을 사용하여 런타임에 동적으로 속성을 설정하는 방법을 보여주는 샘플 Windows Forms 응용 프로그램 샘플을 만들었습니다. 이를 깨끗하게 처리하는 좋은 방법은 아마도 일부 컬렉션 유형을 반복하는 것일 것입니다.

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 
    private void Form1_Load(object sender, EventArgs e) 
    { 
     //This sample shows invocation using a loosely typed object. 
     //Assumes you will send the correct object type to the property setter at runtime 
     Dictionary<string, object> setupObjectValues = new Dictionary<string, object>(); 
     setupObjectValues.Add("Text", "Hello World"); 
     setupObjectValues.Add("ReadOnly", true); 
     setupObjectValues.Add("Location", new Point(10, 5)); 
     foreach (string val in setupObjectValues.Keys) 
     { 
      UpdateControlObjectValue(textBox1, val, setupObjectValues[val]); 
     } 
    } 
    public delegate void SetObjectPropertyDelegate(Control param, string PropertyName, object NewValue); 
    public void UpdateControlObjectValue(Control sender, string PropertyName, object Value) 
    { 
     //Pass the method name into the delegate and match signatures 
     //params collection used for parameters on method called in this case object and string 
     sender.Invoke(new SetObjectPropertyDelegate(SetObjectProperty), sender, PropertyName, Value); 
    } 
    //Called by delegate (Matches signature of SetObjectPropertyDelegate) 
    private void SetObjectProperty(Control sender, string PropertyName, object NewValue) 
    { 
     if (sender == null || String.IsNullOrEmpty(PropertyName) || NewValue == null) 
      throw new ArgumentException("Invalid Argument"); 
     try 
     { 
      //Guaranteed to be a control due to strong typing on parameter declaration 
      sender.GetType().GetProperty(PropertyName).SetValue(sender, NewValue, null); 
      //Set Value on MSDN doc : http://msdn.microsoft.com/en-us/library/xb5dd1f1.aspx 
     } 
     catch (System.Reflection.AmbiguousMatchException ex) 
     { 
      //Two properties were found that match your Property Name 
     } 
     catch (ArgumentNullException ex) 
     { 
      //Null Property Found 
     } 
     catch (ArgumentException ex) 
     { 
      //Invalid Argument 
     } 
     catch (System.Reflection.TargetException ex) 
     { 
      //Invalid Target 
     } 
     catch (System.Reflection.TargetParameterCountException ex) 
     { 
      //Invalid number of parameters passed to reflection invoker 
     } 
     catch (System.MethodAccessException ex) 
     { 
      //Could not access the method to invoke it 
     } 
     catch (System.Reflection.TargetInvocationException ex) 
     { 
      //Problem invoking the target method 
     } 
     catch (Exception ex) 
     { 
      //serious problem 
     } 
    } 
} 

}

관련 문제