C# 从不同类中的不同线程更新UI

C# 从不同类中的不同线程更新UI,c#,.net,winforms,multithreading,backgroundworker,C#,.net,Winforms,Multithreading,Backgroundworker,我有一个主窗体类,它包含一个我想更改的列表框。框中填充了以耗时方法创建的项。现在看起来是这样的(手工制作一个例子,可能是无效的): List strings=StaticClassHelper.GetStrings(inputString); foreach(字符串中的字符串s) { 列表框1.添加; } //同时,在不同的类中,在不同的文件中。。。 公共静态列表GetString(inputString) { 列表结果=新列表(); foreach(inputString.Split('c')

我有一个主窗体类,它包含一个我想更改的列表框。框中填充了以耗时方法创建的项。现在看起来是这样的(手工制作一个例子,可能是无效的):

List strings=StaticClassHelper.GetStrings(inputString);
foreach(字符串中的字符串s)
{
列表框1.添加;
}
//同时,在不同的类中,在不同的文件中。。。
公共静态列表GetString(inputString)
{
列表结果=新列表();
foreach(inputString.Split('c')中的字符串s)
{
结果.添加(s.Reverse());
睡眠(1000);
}
返回结果;
}

我想做的是在发现新字符串时定期更新列表框。当thread方法在同一个类中时,我发现的其他答案也有效,因此可以设置事件处理程序。我在这里做什么?

包含ListBox的类需要公开一个方法来添加字符串-因为这个方法可能在不同的线程上调用,所以需要使用

listBox1.Invoke( ...)

要创建线程安全的调用机制

包含ListBox的类需要公开一个方法来添加字符串-由于此方法可能在不同的线程上调用,因此需要使用

listBox1.Invoke( ...)

要创建线程安全的调用机制,我喜欢这样做,我在表单上创建一个方法,如下所示:

public void AddItemToList(string Item)
{
   if(InvokeRequired)
      Invoke(new Action<string>(AddItemToList), Item);
   else
      listBox1.Add(Item);
}
static class Program
{
   static void Main() 
   {
       MyForm form = new MyForm();
       Application.Run(form);  
   }

}
这通常是我会做的,尤其是在“单一形式”申请的情况下:

static class Program
{
   public static MyForm MainWindow;

   static void Main() 
   {
       mainWindow = new MyForm();
       Application.Run(form);  
   }

}
然后,您几乎可以在任何地方使用它:

Program.MainWindow.AddToList(...);

我喜欢这样做,我在表单上创建一个方法,如下所示:

public void AddItemToList(string Item)
{
   if(InvokeRequired)
      Invoke(new Action<string>(AddItemToList), Item);
   else
      listBox1.Add(Item);
}
static class Program
{
   static void Main() 
   {
       MyForm form = new MyForm();
       Application.Run(form);  
   }

}
这通常是我会做的,尤其是在“单一形式”申请的情况下:

static class Program
{
   public static MyForm MainWindow;

   static void Main() 
   {
       mainWindow = new MyForm();
       Application.Run(form);  
   }

}
然后,您几乎可以在任何地方使用它:

Program.MainWindow.AddToList(...);

您是否可以将GetString重写为迭代器?然后在UI中,您可以启动一个后台线程,该线程迭代GetString的结果,每次都更新listbox。比如:

public static System.Collections.IEnumerable GetStrings(inputString)
{
    foreach(string s in inputString.Split('c'))
    {
        yield return s.Reverse();
        Thread.Sleep(1000);
    }
}
在UI中(假设为C#4):


可能有更干净的方法,但这会让你找到你想要的东西。

你能把GetStrings重写成迭代器吗?然后在UI中,您可以启动一个后台线程,该线程迭代GetString的结果,每次都更新listbox。比如:

public static System.Collections.IEnumerable GetStrings(inputString)
{
    foreach(string s in inputString.Split('c'))
    {
        yield return s.Reverse();
        Thread.Sleep(1000);
    }
}
在UI中(假设为C#4):


可能是更干净的方法,但这应该能让你找到你想要的东西。

我想澄清一下,问题是GetStrings获取每个字符串的速度很慢,每次找到一个字符串时,你都想在后台更新列表框吗?@Bort:是的,就是这样。我想澄清一下,问题是GetStrings获取每个字符串的速度很慢,并且每次找到字符串时都要在后台更新列表框吗?@Bort:是的,就是这样。我明白了。我不明白的是如何在静态方法中引用表单,我明白了。我不明白的是如何在静态方法中引用表单。