我正在尝试使用WinForms
制作.Net
应用。
我正在使用教程from here展示BackgroundWorker
和ProgressBar
整合。
我在表单中添加了ProgressBar
和BackgroundWorker
控件。
名称与示例中的名称相同。另外,我为WorkerReportProgress
将True
属性设置为BackgroundWorker
。没有显示错误,项目编译成功......
问题是 - 进度条不移动。
然而,当手动点击时它会移动...... progressBar1.PerformStep();
。
我缺少什么?
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();
}
}
}
从progressBar1.PerformStep();
和DoWork
移除了ProgressChanged
。
问题仍然存在(ProgressBar不会移动)。
感谢您提出的建议,我们将在周一进行更多调查。
答案 0 :(得分:1)
确定已将事件处理程序附加到ProgressChanged
和DoWork
后:
progressBar1.PerformStep()
事件处理程序中删除DoWork
。progressBar1.Value = e.ProgressPercentage;
事件处理程序中使用ProgressChanged
。答案 1 :(得分:0)
几年前我写了一个带有Progress条形码的简单多线程。希望它可以帮到你:
#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
通常在从Alterante线程编写UI元素时,您必须使用Invoke。 BackgroundWorker非常好,并且在创建它的线程上调用“ReportProgress”和“RunWorkerCompleted”事件(应该是GUI线程),所以你不必处理多线程盘旋的那部分。
它也足以捕获通常会逃避DoWork并被吞噬的任何异常,并在完成事件Args中将它们暴露给您。吞咽异常是多线程的一个大问题。
核心问题是,你的循环因异常而中断。在内部调用progressBar1.PerformStep();
DoWork事件必须抛出“CrossThreadException”。 BackgroudnWorker立即完成(由于例外)。当我只是初始值时,会触发RunWorker completed事件。