gpt4 book ai didi

C# - 在多线程环境中使用 listbox.BeginUpdate/listbox.EndUpdate 不工作

转载 作者:行者123 更新时间:2023-11-30 17:20:00 27 4
gpt4 key购买 nike

除了一个问题,我手头的任务几乎完成了。我正在尝试通过 beginupdate() 和 endupdate() 通过 backgroundWorker 线程控制列表框 ui 的更新,该线程也用于更新我的进度条。我在想在项目列表上加一个锁或监视器就足够了(在绘制时需要解析列表的情况下),但无济于事。有人有什么想法吗?

这里是相关代码...

编辑:显示通过另一个线程将项目添加到列表中。

private void backgroundWorker4_DoWork(object sender, DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker worker = sender as BackgroundWorker;

// Number of intervals
int stop = 60;

for (int i = 1; i <= stop; i++)
{
if (worker.CancellationPending)
{
e.Cancel = true;
backgroundWorker4.ReportProgress(0);
return;
}

//listBoxBeginUpdate(listBox1);

// Half second intervals
//listBox1.BeginUpdate();
//listBox1.EndUpdate();
//ListBox.listBoxBeginUpdate(listBox1);
listBoxBeginUpdate(listBox1);
Thread.Sleep(500);
listBoxEndUpdate(listBox1);

listBoxBeginUpdate(listBox1);
Thread.Sleep(500);
listBoxEndUpdate(listBox1);

// Update every second
//listBoxEndUpdate(listBox1);

int progress = i * 100 / stop;
backgroundWorker4.ReportProgress(progress);

//updateProgressBar = !updateProgressBar;
}
}
public static void listBoxBeginUpdate(System.Windows.Forms.ListBox varListBox)
{
if (varListBox.InvokeRequired)
{
varListBox.BeginInvoke(new MethodInvoker(() => listBoxBeginUpdate(varListBox)));
}
else
{
// Request the lock, and block until it is obtained.
Monitor.Enter(varListBox);
try
{
// When the lock is obtained, add an element.
varListBox.BeginUpdate();
}
finally
{
// Ensure that the lock is released.
Monitor.Exit(varListBox);
}
}
}

public static void listBoxEndUpdate(System.Windows.Forms.ListBox varListBox)
{
if (varListBox.InvokeRequired)
{
varListBox.BeginInvoke(new MethodInvoker(() => listBoxEndUpdate(varListBox)));
}
else
{
// Request the lock, and block until it is obtained.
Monitor.Enter(varListBox);
try
{
// When the lock is obtained, add an element.
varListBox.EndUpdate();
}
finally
{
// Ensure that the lock is released.
Monitor.Exit(varListBox);
}

//lock (varListBox.Items)
//{
// Monitor.Enter(varList
// varListBox.EndUpdate();
//}
}
}

// Added to show the thread adding items into the list
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker worker = sender as BackgroundWorker;
Random random = new Random();

//Stopwatch stopwatch = new Stopwatch();
//stopwatch.Start();

while(_threadsRunning)
{
if (worker.CancellationPending)
{
e.Cancel = true;
return;
}

System.Threading.Thread.Sleep(1000);

int numberOfItems = random.Next(5, 10);
for (int i = 5; i < numberOfItems; i++)
{
int number = random.Next(1, 10000);
listBoxAddItem(listBox1, number);
}

backgroundWorker1.ReportProgress(numberOfItems);
}
}

public static void listBoxAddItem(System.Windows.Forms.ListBox varListBox, int item)
{
if (varListBox.InvokeRequired)
{
varListBox.BeginInvoke(new MethodInvoker(() => listBoxAddItem(varListBox, item)));
}
else
{
varListBox.Items.Add(item);
}
}

最佳答案

这很复杂。您有 backgroundWorker1,它似乎只是向 UI 线程发送一条消息(通过 Control.BeginInvoke)指示它向 添加一个项目列表框。同时,backgroundWorker4 只是向 UI 线程发送消息,指示它调用 BeginUpdateEndUpdate

  • UI 更新仍在 UI 线程上进行。一方面这很好,因为您绝对不能从创建它的线程以外的线程访问 UI 元素。但是,由于您的工作线程只是向 UI 线程发送消息,所以它们几乎毫无意义。事实上,它实际上让事情变得更慢。

  • BeginUpdateEndUpdateAdd 方法的顺序将完全随机。我打赌你不会得到你想要的行为。

  • 锁定(通过 Monitor.EnterMonitor.Exit)也毫无意义。由于锁只在 UI 线程上获取,因此永远不会有任何争用。

  • 使用 Control.BeginInvokeControl.Invoke 来弥合 UI 和工作线程之间的差距被滥用了。个人认为这个话题是argumentum ad populum的牺牲品| .很多时候,最好让 UI 线程定期(通过 System.Windows.Forms.Timer)轮询工作线程正在更新的共享数据结构。

关于C# - 在多线程环境中使用 listbox.BeginUpdate/listbox.EndUpdate 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4467732/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com