使用线程每隔2秒更改listBox的选定索引
本文关键字:listBox 索引 线程 2秒 | 更新日期: 2023-09-27 18:20:07
我想每两秒钟更改一次列表框所选索引的索引。
public Form1()
{
InitializeComponent();
listBox1.Items.Add("A");
listBox1.Items.Add("B");
listBox1.Items.Add("C");
listBox1.Items.Add("D");
listBox1.Items.Add("E");
listBox1.Items.Add("F");
}
public void SelectEvery2Sec()
{
System.Windows.Forms.Timer timer=new System.Windows.Forms.Timer();
for (int i = 0; i < listBox1.Items.Count; i++)
{
timer.Start();
listBox1.SelectedIndex = i;
try
{
Thread.Sleep(2000);
}
catch{}
if(i == listBox1.Items.Count -1)
i = 0;
}
}
但我们无法停止主线程。然后应用程序运行,但我看不到GUI。这是不正确的方式,所以我尝试下一种方式,即另一个线程。
然后我将创建一个新的线程,但线程的交叉访问是不允许的?
然后我将创建一个新的线程,但线程的交叉访问是不允许的?
正确。不能从非UI线程访问UI控件。如果你尝试,你会得到一个例外。
在任何情况下,多线程都不一定是正确的解决方案。对于这种情况,计时器控件可能更简单——您想要的控件称为System.Windows.Forms.Timer
。
或者,您可以使用BackgroundWorker
组件。你所要做的就是在设计时将它添加到你的表单中,它会为你处理所有的脏活。MSDN页面上有一个很棒的示例。
请注意,Thread.Sleep
是程序设计不佳的标志。如果你发现自己在代码中写了这些,那你就错了。几乎可以肯定有更好的方法。
这种类型的问题在Stack Overflow上被问了很多。您可以通过执行搜索来查找更多信息。
您可以使用Timer
或BackgroundWorker
来执行此操作。对于Timer
,将Interval
设置为2秒。对于BackgroundWorker
,请使用RunWorkerAsync
。
对于cross thread access issue
,使用
public static class ControlExtensions
{
public static void Invoke(this Control control, Action action)
{
if (control.InvokeRequired) control.Invoke(new MethodInvoker(action), null);
else action.Invoke();
}
}
您的旧代码
listBox1.SelectedIndex = i;
将成为
listBox1.Invoke(() => { listBox1.SelectedIndex = i; });
使用System.Threading.Timer
而不是System.Windows.Forms.Timer
。这可以在工作线程中运行。
让计时器超时事件处理程序调用一个函数来更改ListBox.SelectedItem
,确保在更改ListBox所选项目时检查Invoke.Required
,因为您可能需要Invoke
。
将定时器对象的Interval
设置为2000ms,不使主线程休眠。
您可以hanndle Timer Elapsed事件并更新控件。
更新:
要让它由两个线程组成,请每隔2000毫秒在第二个线程中引发一个事件,并将Form中的一个方法连接到它。在该方法中,您可以更改窗体的控件。