private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int currentProgress=-1;
while (currentProgress<length)
{
currentProgress=Worker.progress;
backgroundWorker1.ReportProgress(currentProgress);
Thread.Sleep(500);
length = Worker.UrlList.Count;
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
int ix = e.ProgressPercentage;
progressBar1.Value = ix;
lblText.Text =ix+" %";
}
我写了一个程序,通过阅读文件下载页面源有大约1000个URL。所以我用Tasks来下载异步页面。这里Worker.progress
是当前执行的URL数量。虽然debuger击中backgroundWorker1.ReportProgress(currentProgress);
,但它永远不会进入backgroundWorker1_ProgressChanged
。
private void StartButton_Click(object sender, EventArgs e)
{
t.makeUrlList(inputFile);
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
backgroundWorker1.RunWorkerAsync();
t.RunTasks();
Application.Exit();
}
后台工作人员在启动按钮点击时初始化...
这是创建我的任务的地方....
public void RunTasks()
{
if (numOfTasks > UrlList.Count)
numOfTasks=UrlList.Count-1;
Task[] t = new Task[numOfTasks];
int j = 0;
while ( j < UrlList.Count-1)
{
for (int i = 0; (i < t.Count())&&(j<UrlList.Count-1); i++)
{
try
{
if (t[i].IsCompleted || t[i].IsCanceled || t[i].IsFaulted)
{
t[i] = Task.Run(() => FindWIN(j));
j++;
progress = j;
}
}
catch (NullReferenceException ex)
{
t[i] = Task.Run(() => FindWIN(j));
j++;
progress = j;
}
}
}
}
答案 0 :(得分:3)
如果您希望BackgroundWorker支持更新进度信息,则应将WorkerReportsProgress的值设置为true。如果此属性为true,则用户代码可以调用ReportProgress来启动事件ProgressChanged。
后台工作程序初始化: -
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork+=backgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged+=backgroundWorker1_ProgressChanged;
backgroundWorker1.RunWorkerAsync();
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int currentProgress = -1;
decimal length=1000;
while (currentProgress < length)
{
currentProgress = Worker.progress;
backgroundWorker1.ReportProgress(currentProgress);
Thread.Sleep(500);
length = Worker.UrlList.Count;
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) {
int ix = e.ProgressPercentage;
progressBar1.Value = ix;
lblText.Text = ix + " %";
}
答案 1 :(得分:2)
在初始化阶段,您应该将worker的WorkerReportsProgress属性设置为true。
答案 2 :(得分:2)
请参阅下面的演示代码。这大多是未经测试的,当然不是生产标准,但它应该会给你一个良好的开端!
它使用ConcurrentQueue
来保存要处理的网址列表。这是线程安全的,让生活更轻松。
它具有可配置数量的网址和任务。最好不要完成1000个任务,而是拥有一个工作项队列,以及一个较小的任务池,它可以提取项目&#39;离开队列,直到它排空。这意味着您可以对不同数量的任务进行性能测试,并为您的问题找到最佳价值。
更新进度条时使用Invoke - 这可以避免跨线程异常。
否BackgroundWorker
- 仅TaskFactory
和Task
public partial class Form1 : Form
{
private const int UrlCount = 1000;
private const int taskCount = 10;
private ConcurrentQueue<string> urlList;
private List<Task> taskList;
public Form1()
{
InitializeComponent();
}
private void ResetQueue()
{
// fake up a number of strings to process
urlList = new ConcurrentQueue<string>(Enumerable.Range(0, UrlCount)
.Select(i => "http://www." + Guid.NewGuid().ToString() + ".com"));
}
private void button1_Click(object sender, EventArgs e)
{
ResetQueue();
var taskFactory = new TaskFactory();
// start a bunch of tasks
taskList = Enumerable.Range(0, taskCount).Select(i => taskFactory.StartNew(() => ProcessUrl()))
.ToList();
}
void ProcessUrl()
{
string current;
// keep grabbing items till the queue is empty
while (urlList.TryDequeue(out current))
{
// run your code
FindWIN(current);
// invoke here to avoid cross thread issues
Invoke((Action)(() => UpdateProgress()));
}
}
void FindWIN(string url)
{
// your code here
// as a demo, sleep a sort-of-random time between 0 and 100 ms
Thread.Sleep(Math.Abs(url.GetHashCode()) % 100);
}
void UpdateProgress()
{
// work out what percentage of the queue is processed
progressBar1.Value = (int)(100 - ((double)urlList.Count * 100.0 / UrlCount));
}
}