带标签的进度条-无法更新ProgressChanged中的标签
本文关键字:标签 更新 ProgressChanged | 更新日期: 2023-09-27 18:01:47
我有一个后台工作人员长时间运行的任务。该任务遍历一个文件列表,我想要更新我们正在使用的文件的用户。我有一个工具条,它的标签名为panel1.text。进度条正在工作,但是我的ProgressChanged方法中的标签没有改变,即它应该说处理File1,然后更改为处理File2,但它保持默认的处理。
private void btnProcess_Click(object sender, EventArgs e)
{
toolStripProgressBar1.Visible = true;
toolStripProgressBar1.Maximum = 1000000000;
panel1.Text = "Processing "; // this appears properly
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(processFiles);
worker.ProgressChanged += ProgressChanged;
worker.RunWorkerAsync();
while (worker.IsBusy)
{
// the reason for this is because nothing can happen until the processing is done
toolStripProgressBar1.Increment(1);
}
// more processing
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
panel1.Text = "Processing "+ e.UserState.ToString(); <<<---- This is Not Updating panel1.Text but it evaluates properly
}
private void processFiles(object sender, EventArgs e)
{
int retVal = 0;
foreach (string fileName in listBox1.Items)
{
ProgressChangedEventArgs ea = new ProgressChangedEventArgs(1,fileName);
ProgressChanged(this, ea);
// do more processing
}
}
我将感激任何帮助。
您正在使用同一线程,该线程被另一个进程阻塞。您需要使用Task来创建一个新线程,可能还需要使用Dispatcher。如果控件在另一个线程上,则调用beginiinvoke。确保任何Button Click等正在发生的事情都用Async关键字标记,以使其异步。
的例子:
Await Task mytask = Task.Run(() =>
for(var i = 0; i < 1000; i++)
{
Label.Dispatcher.BeginInvoke( () =>
UpdateMe(int i, LabelClass/Component class/component)});
然后在标签类内部或标签所在的地方:
Public void UpdateMe(int i, LabelClass class)
{
class.label.content = Cint((i/Total)*100);
Thread.Sleep(500);
}
还有其他方法可以做到这一点,比如将值绑定到UI,但这将让你更好地理解为什么它不起作用,以及其他线程是如何工作的。
如果你想真正获得视觉理解,请调用:
`Console.WriteLine($"Current Thread ID: System.Threading.Thread.CurrentThread.ManagedThreadId}");`
就在你进入Task之前——它会给你主线程ID然后在Task中再次调用它…这将给你第二个线程ID。
然后在Dispatcher调用之前:
Console.WriteLine($"Do I have access to the label on this thread? {Label.Dispatcher.CheckAccess()}";
如果你有访问权限,它将显示True,如果没有,它将显示False…在你的例子中,它将显示false,因为它属于另一个线程,但是你可以使用Dispatcher在另一个线程中处理该线程的工作…
另外,我建议你不要使用后台工作器,而是使用任务…这就解释了为什么……基本上,任务可以完成后台工作人员所做的一切,甚至更多,问题更少,更容易使用…
http://blog.stephencleary.com/2013/09/taskrun-vs-backgroundworker-conclusion.html正如Ivan已经评论的那样,删除while循环while (worker.IsBusy)
,因为它阻塞了UI线程以进一步处理。同样,您应该启用WorkerReportsProgress
到true
worker.WorkerReportsProgress = true;
worker.ProgressChanged += ProgressChanged;
while (!worker.IsBusy)
{
worker.RunWorkerAsync();
}
根据您的评论,将这些后期处理移动到BackgroundWorker。RunWorkerCompleted事件