【发布时间】:2018-03-17 09:53:55
【问题描述】:
我不知道如何使用 WinForms 中的 BackgroundWorker 来实现具有单独线程的方法。 我希望执行此方法(每次单击按钮后):
- 创建 ProgressBar(每个新的在前一个之下)
- 创建位图和BackgroundWorker
- 使用 BackgroundWorker 在单独的线程中设置该位图中每个像素的颜色
- 在 ProgressBar 上显示百分比进度
- 完成后:在背景上创建一个带有位图的新表单
- 完成后:移除 ProgressBar
我的代码:
List<BackgroundWorker> Workers;
List<ProgressBar> Progress;
int OperationsCount = 0;
private void ShowProgress(int n, int percent)
{
Progress[n].Value = percent;
}
private void Blend(object sender, DoWorkEventArgs e)
{
Bitmap BlendedImage = ... // creates a bitmap
for (int i = 0; i < BlendedImage.Width; i++)
{
for (int j = 0; j < BlendedImage.Height; j++)
{
... //changing colour of every pixel
}
this.Invoke(new Action(()=>ShowProgress((int)e.Argument, (int)(100 * (double)(i/BlendedImage.Width)))));
}
Form BlendedImage_Form = new Form();
BlendedImage_Form.Size = new Size(BlendedImage.Width, BlendedImage.Height);
BlendedImage_Form.BackgroundImage = BlendedImage;
BlendedImage_Form.BackgroundImageLayout = ImageLayout.Stretch;
this.Invoke(new Action(() => BlendedImage_Form.Show()));
}
private void PerformBlending_Button_Click(object sender, EventArgs e)
{
int n = OperationsCount++;
Progress.Add(new ProgressBar());
Progress[n].Size = ...
Progress[n].Location = ...
Progress[n].Maximum = 100;
this.Controls.Add(Progress[n]);
Workers.Add(new BackgroundWorker());
Workers[n].DoWork += new DoWorkEventHandler(Blend);
Workers[n].RunWorkerCompleted += (object _sender, RunWorkerCompletedEventArgs _e) =>
{
//OperationsCount--;
//Progress[n].Dispose();
//this.Controls.Remove(Progress[n]);
//Progress.RemoveAt(n);
};
Workers[n].RunWorkerAsync(n);
}
当我只单击一次按钮时,一切似乎都很好,但是当我单击两次按钮时,然后编程:
- 创建第一个正确显示进度的 ProgressBar,并且新表单和位图也正确显示
- 创建了第二个 ProgressBar,但它根本不显示进度,也没有显示任何表单和位图。
PS 我宁愿使用 BackgroundWorker 而不是其他工具。
【问题讨论】:
-
你在哪里实例化这些列表?
-
所有 UI 工作都应该在主线程上。即使您使用的是 BackgroundWoker,您也需要修改主线程上的控件。
-
@Groo in public MainWindow()
-
(double)(i/BlendedImage.Width) 是一个标准的 C# 错误,它总是产生 0。你必须要求浮点除法,((double)i / BlendedImage.Width)
-
@Adrian 那么如何在改变像素颜色后返回位图呢?我需要它在我的表单中显示它
标签: c# multithreading winforms