从不同类中的不同线程更新 UI
我有主窗体类,其中包含我想要更改的列表框。盒子里装满了通过耗时的方法创建的项目。现在它看起来像这样(手工发明一个示例,可能不是有效的 C#):
List<string> strings = StaticClassHelper.GetStrings(inputString);
foreach(string s in strings)
{
listBox1.Add(s);
}
//meanwhile, in a different class, in a different file...
public static List<string> GetStrings(inputString)
{
List<string> result = new List<string>();
foreach(string s in inputString.Split('c'))
{
result.Add(s.Reverse());
Thread.Sleep(1000);
}
return result;
}
我想做的是在发现新字符串时定期更新列表框。当线程方法位于同一个类中时,我发现其他答案有效,因此您可以设置事件处理程序。我在这里做什么?
I have the main form class which contains a list box I want to change. The box is populated with items created in a time-consuming method. Right now it looks like this (inventing an example by hand, might not be valid C#):
List<string> strings = StaticClassHelper.GetStrings(inputString);
foreach(string s in strings)
{
listBox1.Add(s);
}
//meanwhile, in a different class, in a different file...
public static List<string> GetStrings(inputString)
{
List<string> result = new List<string>();
foreach(string s in inputString.Split('c'))
{
result.Add(s.Reverse());
Thread.Sleep(1000);
}
return result;
}
What I would like to do instead is regularly update the list box as new strings are found. The other answers I found work when the thread method is in the same class, so you can set up an event handler. What do I do here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我喜欢这样做,我在表单上创建一个方法,如下所示:
我更喜欢在这种情况下调用以确保同步添加项目,否则它们可能会乱序。如果您不关心顺序,那么您可以使用
BeginInvoke
,这会更快一些。由于此方法是公共的,因此只要您可以获得对表单的引用,您就可以从应用程序中的任何类中使用它。这样做的另一个优点是,您可以从 UI 线程或非 UI 线程调用它,并且它负责决定是否需要 Invoke。这样你的调用者就不需要知道他们正在哪个线程上运行。
更新
为了解决您关于如何获取对
Form
的引用的评论,通常在 Windows 窗体应用程序中,您的 Program.cs 文件看起来像这样:这通常是我会做的,特别是在以下情况下“单一表单”应用程序:
然后您几乎可以在任何地方通过以下方式访问它:
Here is how I like to do this, I create a method on the form like this:
I prefer invoke in this case to make sure the items are added synchronously, otherwise they can get out of order. If you don't care about the order then you can use
BeginInvoke
which will be a tad faster. Since this method is public, you can all it from any class in your application as long as you can get a reference to your form.Another advantage of this is that you can call it from either your UI thread or a non-UI thread and it takes care of deciding whether or not it needs
Invoke
ing. This way your callers don't need to be aware of which thread they are running on.UPDATE
To address your comment about how to get a reference to the
Form
, typically in a Windows Forms app your Program.cs file looks something like this:This is typically what I would do, particularly in the case of a "Single Form" application:
And then you can access it pretty much anywhere with:
包含 ListBox 的类需要公开一个方法来添加字符串 - 由于该方法可能在不同的线程上调用,因此需要使用它
来创建线程安全的调用机制
The class containing the ListBox needs to expose a method to add a string - since this method might be called on a different thread, it needs to use
to create a thread-safe calling mechanism
您可以将 GetStrings 重写为迭代器吗?然后,在您的 UI 中,您可以启动一个后台线程来迭代 GetStrings 的结果,每次更新列表框。类似于:
在 UI 中(假设 C# 4):
可能是更简洁的方法,但这应该可以满足您的需求。
Would it be possible for you to rewrite GetStrings as an Iterator? Then in your UI you could start a background thread which iterates over the results of GetStrings, updating the listbox each time. Something like:
And in the UI (Assuming C# 4):
Probably cleaner ways to go about it, but this should get you what you're looking for.