Comment mettre à jour l'interface graphique depuis un autre thread ?

Comment mettre à jour l’interface graphique depuis un autre thread ?

Pour .NET 2.0, voici un joli bout de code que j’ai écrit qui fait exactement ce que vous souhaitez, et fonctionne pour n’importe quelle propriété d’un Control :

private delegate void SetControlPropertyThreadSafeDelegate(
    Control control,
    string propertyName,
    object propertyValue);

public static void SetControlPropertyThreadSafe(
    Control control,
    string propertyName,
    object propertyValue)
{
  if (control.InvokeRequired)
  {
    control.Invoke(new SetControlPropertyThreadSafeDelegate
    (SetControlPropertyThreadSafe),
    new object[] { control, propertyName, propertyValue });
  }
  else
  {
    control.GetType().InvokeMember(
        propertyName,
        BindingFlags.SetProperty,
        null,
        control,
        new object[] { propertyValue });
  }
}

Appelez-le comme ceci :

// thread-safe equivalent of
// myLabel.Text = status;
SetControlPropertyThreadSafe(myLabel, "Text", status);

Si vous utilisez .NET 3.0 ou supérieur, vous pourriez réécrire la méthode ci-dessus comme une méthode d’extension de la classe Control, ce qui simplifierait l’appel en :

myLabel.SetPropertyThreadSafe("Text", status);

MISE À JOUR 05/10/2010 :

Pour .NET 3.0, vous devriez utiliser ce code :

private delegate void SetPropertyThreadSafeDelegate<TResult>(
    Control @this,
    Expression<Func<TResult>> property,
    TResult value);

public static void SetPropertyThreadSafe<TResult>(
    this Control @this,
    Expression<Func<TResult>> property,
    TResult value)
{
  var propertyInfo = (property.Body as MemberExpression).Member
      as PropertyInfo;

  if (propertyInfo == null ||
      [email protected]().IsSubclassOf(propertyInfo.ReflectedType) ||
      @this.GetType().GetProperty(
          propertyInfo.Name,
          propertyInfo.PropertyType) == null)
  {
    throw new ArgumentException("The lambda expression 'property' must reference a valid property on this Control.");
  }

  if (@this.InvokeRequired)
  {
      @this.Invoke(new SetPropertyThreadSafeDeleg

*(Réponse tronquée)*