[英]Progressbar does not move (WinForms, .Net and BackgroundWorker)
I am trying to make a WinForms
app using .Net
. 我正在尝试使用
.Net
制作WinForms
应用程序。
I am using tutorial from here wich shows BackgroundWorker
and ProgressBar
integration. 我正在使用从这里开始的教程,该教程显示了
BackgroundWorker
和ProgressBar
集成。
I added ProgressBar
and BackgroundWorker
controls to the form. 我向表单添加了
ProgressBar
和BackgroundWorker
控件。 The names are the same as in example. 名称与示例中的相同。 Additionaly, i set
WorkerReportProgress
property to True
for BackgroundWorker
. Additionaly,我设置
WorkerReportProgress
属性为True
为BackgroundWorker
。 No errors are shown and project compiles sucessfully... 没有错误显示,项目成功编译...
The problem is - progressbar does not move. 问题是-进度栏不会移动。 And yet, it moves when clicked manually...
progressBar1.PerformStep();
但是,当手动单击时它会移动...
progressBar1.PerformStep();
. 。
What am i missing? 我想念什么?
Form1.cs Form1.cs的
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, System.EventArgs e)
{
// Start the BackgroundWorker.
BackgroundWorker1.RunWorkerAsync();
}
private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i <= 100; i++)
{
// Wait 500 milliseconds.
Thread.Sleep(500);
// Report progress.
BackgroundWorker1.ReportProgress(i);
}
}
private void BackgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Change the value of the ProgressBar to the BackgroundWorker progress.
progressBar1.Value = e.ProgressPercentage;
// Set the text.
this.Text = e.ProgressPercentage.ToString();
}
private void button2_Click(object sender, EventArgs e)
{
progressBar1.PerformStep();
}
}
}
Removed progressBar1.PerformStep();
删除了
progressBar1.PerformStep();
from DoWork
and ProgressChanged
. 来自
DoWork
和ProgressChanged
。 Still the problem persists (ProgressBar does not move). 问题仍然存在(ProgressBar不会移动)。
Thank you for ideas so far, will look into it more on Monday. 到目前为止,谢谢您的想法,我们将在星期一进行更多探讨。
After you made sure you attached the event handlers to ProgressChanged
and DoWork
: 确保将事件处理程序附加到
ProgressChanged
和DoWork
:
progressBar1.PerformStep()
from DoWork
event handler. DoWork
事件处理程序中删除progressBar1.PerformStep()
。 progressBar1.Value = e.ProgressPercentage;
progressBar1.Value = e.ProgressPercentage;
in ProgressChanged
event handler. ProgressChanged
事件处理程序中。 I wrote a simple Multithreading with Progress bar code a few years back. 几年前,我写了一个带有进度条码的简单多线程。 Hope it helps you:
希望它可以帮助您:
#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
if (!bgwPrim.IsBusy)
{
//Prepare ProgressBar and Textbox
int temp = (int)nudPrim.Value;
pgbPrim.Maximum = temp;
tbPrim.Text = "";
//Start processing
bgwPrim.RunWorkerAsync(temp);
}
}
private void btnPrimCancel_Click(object sender, EventArgs e)
{
if (bgwPrim.IsBusy)
{
bgwPrim.CancelAsync();
}
}
private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
int highestToCheck = (int)e.Argument;
//Get a reference to the BackgroundWorker running this code
//for Progress Updates and Cancelation checking
BackgroundWorker thisWorker = (BackgroundWorker)sender;
//Create the list that stores the results and is returned by DoWork
List<int> Primes = new List<int>();
//Check all uneven numbers between 1 and whatever the user choose as upper limit
for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
{
//Report progress
thisWorker.ReportProgress(PrimeCandidate);
bool isNoPrime = false;
//Check if the Cancelation was requested during the last loop
if (thisWorker.CancellationPending)
{
//Tell the Backgroundworker you are canceling and exit the for-loop
e.Cancel = true;
break;
}
//Determin if this is a Prime Number
for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
{
if (PrimeCandidate % j == 0)
isNoPrime = true;
}
if (!isNoPrime)
Primes.Add(PrimeCandidate);
}
//Tell the progress bar you are finished
thisWorker.ReportProgress(highestToCheck);
//Save Return Value
e.Result = Primes.ToArray();
}
private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pgbPrim.Value = e.ProgressPercentage;
}
private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
pgbPrim.Value = pgbPrim.Maximum;
this.Refresh();
if (!e.Cancelled && e.Error == null)
{
//Show the Result
int[] Primes = (int[])e.Result;
StringBuilder sbOutput = new StringBuilder();
foreach (int Prim in Primes)
{
sbOutput.Append(Prim.ToString() + Environment.NewLine);
}
tbPrim.Text = sbOutput.ToString();
}
else
{
tbPrim.Text = "Operation canceled by user or Exception";
}
}
#endregion
Normally when writing a UI Element from a Alterante Thread, you have to use Invoke . 通常,当从Alterante线程编写UI元素时,必须使用Invoke 。 BackgroundWorker is nice and Invoking the "ReportProgress" and "RunWorkerCompleted" Events on the thread that created it (wich should be the GUI thread) so you do not have to deal with that part of Multithreading wonkyness yet.
BackgroundWorker很不错,可以在创建它的线程(应该是GUI线程)上调用“ ReportProgress”和“ RunWorkerCompleted”事件,因此您不必处理多线程处理的那部分。
It is also nice enough to catch any Exceptions that would normally escape DoWork and be swallowed, exposing them to you in the Completed Event Args. 它也足以捕获通常会逃避DoWork并被吞下的所有异常,并在Completed Event Args中向您公开。 Swallowing Exceptions is a huge issue with Multithreading.
吞咽异常是多线程的一个巨大问题。
The core issue is, that your loop breaks due to a Exception. 核心问题是循环由于异常而中断。 Calling
progressBar1.PerformStep();
调用
progressBar1.PerformStep();
inside the DoWork Event has to throw a "CrossThreadException". 里面的DoWork的事件不得不抛出一个“CrossThreadException”。 The BackgroudnWorker finishes (due to an exception) instantly.
BackgroudnWorker立即完成(由于异常)。 The RunWorker completed event is triggered when i was just the initial value.
当我只是初始值时,将触发RunWorker完成事件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.