如何更新从C#中的另一个线程的GUI? [英] How to update the GUI from another thread in C#?

查看:239
本文介绍了如何更新从C#中的另一个线程的GUI?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是更新标签最简单的方式从另一个线程?

What is the simplest way to update a Label from another thread?

我有一个表格线程1 ,从我开始另一个线程(线程2 )。虽然线程2 正在处理一些文件,我想更新表格标签 code>与当前状态线程2 的工作。

I have a Form on thread1, from that I'm starting another thread (thread2). While thread2 is processing some files I would like to update a Label on the Form with the current status of thread2's work.

我怎么能这样做?

推荐答案

有关.NET 2.0中,这里有code不错有点我写的不正是你想要什么,而且适用于任何财产上的控制

For .NET 2.0, here's a nice bit of code I wrote that does exactly what you want, and works for any property on a 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 });
  }
}

这样称呼它:

Call it like this:

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

如果您使用的是.NET 3.0或以上,你可以把上面的方法为控制类,然后将简化呼叫的扩展方法:

If you're using .NET 3.0 or above, you could rewrite the above method as an extension method of the Control class, which would then simplify the call to:

myLabel.SetPropertyThreadSafe("Text", status);

更新05/10/2010:

有关.NET 3.0,你应该使用code:

For .NET 3.0 you should use this 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 ||
      !@this.GetType().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 SetPropertyThreadSafeDelegate<TResult> 
      (SetPropertyThreadSafe), 
      new object[] { @this, property, value });
  }
  else
  {
      @this.GetType().InvokeMember(
          propertyInfo.Name, 
          BindingFlags.SetProperty, 
          null, 
          @this, 
          new object[] { value });
  }
}

它使用LINQ和lambda EX pressions允许更清洁,更简单和更安全的语法:

which uses LINQ and lambda expressions to allow much cleaner, simpler and safer syntax:

myLabel.SetPropertyThreadSafe(() => myLabel.Text, status); // status has to be a string or this will fail to compile

不仅是现在在编译时检查的属性名称,属性的类型是一样,所以这是不可能的(例如)分配一个字符串值布尔属性,从而导致运行时异常。

Not only is the property name now checked at compile time, the property's type is as well, so it's impossible to (for example) assign a string value to a boolean property, and hence cause a runtime exception.

不幸的是,这并不不要做傻事阻止任何人如在传递另一个控制的属性和值,所以下面将愉快地编译:

Unfortunately this doesn't stop anyone from doing stupid things such as passing in another Control's property and value, so the following will happily compile:

myLabel.SetPropertyThreadSafe(() => aForm.ShowIcon, false);

于是我加入了运行时检查,以确保传入的属性不会真正属于控制,该方法的调用上。并不完美,但依然有很多比.NET 2.0的版本更好。

Hence I added the runtime checks to ensure that the passed-in property does actually belong to the Control that the method's being called on. Not perfect, but still a lot better than the .NET 2.0 version.

如果任何人有关于如何改进这个$ C $下编译时安全的任何进一步的建议,请发表评论!

If anyone has any further suggestions on how to improve this code for compile-time safety, please comment!

这篇关于如何更新从C#中的另一个线程的GUI?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆