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)*