C#多BackgroundWorkers [英] C# Multiple BackgroundWorkers
问题描述
我想设置多个的BackgroundWorker
s到做工作,不忙的时候开始做下一个工作位。我似乎无法让他们正常工作。我有下面的代码。
当我设置 FilesToProcess
等于或小于 MaxThreads
它完美但如果我让越高,应用程序冻结。
我相信这是简单的东西,但我无法看到它。
感谢您的任何帮助:)
周杰伦
使用系统;
使用System.ComponentModel;
使用的System.Threading;使用System.Windows.Forms的
;
命名空间bgwtest
{
公共部分Form1类:表格
{
私人const int的MaxThreads = 20;
私人const int的FilesToProcess = 21;
私人BackgroundWorker的[] threadArray =新的BackgroundWorker [MaxThreads]
公共Form1中()
{
的InitializeComponent();
}
私人无效Form1Load(对象发件人,EventArgs五)
{
InitializeBackgoundWorkers();
}
私人无效InitializeBackgoundWorkers()
{
为(VAR F = 0; F< MaxThreads;˚F++)
{
threadArray [F] =新的BackgroundWorker();
threadArray [F] .DoWork + =新DoWorkEventHandler(BackgroundWorkerFilesDoWork);
threadArray [F] .RunWorkerCompleted + =新RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted);
threadArray [F] .WorkerReportsProgress = TRUE;
threadArray [F] .WorkerSupportsCancellation = TRUE;
}
}
私人无效的button1_Click(对象发件人,EventArgs五)
{
为(VAR F = 0; F< FilesToProcess;˚F++ )
{
VAR fileProcessed = FALSE;
,而(fileProcessed!)
{
为(VAR threadNum = 0; threadNum< MaxThreads; threadNum ++)!
{
如果(threadArray [threadNum] .IsBusy )
{
Console.WriteLine(启动主题:{0},threadNum);
threadArray [threadNum] .RunWorkerAsync(F);
fileProcessed = TRUE;
中断;
}
}
如果(fileProcessed!)
{
Thread.sleep代码(50);
}
}
}
}
私人无效BackgroundWorkerFilesDoWork(对象发件人,DoWorkEventArgs E)
{
ProcessFile(( INT)e.Argument);
e.Result =(INT)e.Argument;
}
私有静态无效ProcessFile(INT文件)
{
Console.WriteLine(处理文件:{0},文件);
}
私人无效BackgroundWorkerFilesRunWorkerCompleted(对象发件人,RunWorkerCompletedEventArgs E)
{
如果(e.Error!= NULL)
{
MessageBox.Show(e.Error.Message);
}
Console.WriteLine(已处理文件:{0}(INT)e.Result);
}
}
}
这个问题似乎是,你的工人永远不会完成。这是为什么,我不知道;它是与事实,你是从运行它们的方法(和线程)自身没有完成。我能够通过创建另一个工人将文件分配给工人阵列来解决这个问题:
私人BackgroundWorker的assignmentWorker;
私人无效InitializeBackgoundWorkers(){
assignmentWorker =新的BackgroundWorker();
assignmentWorker.DoWork + = AssignmentWorkerOnDoWork;
// ...
}
私人无效AssignmentWorkerOnDoWork(对象发件人,DoWorkEventArgs doWorkEventArgs){
为(VAR F = 0; F< FilesToProcess;˚F++ ){
VAR fileProcessed = FALSE;
,而(fileProcessed!){
为(VAR threadNum = 0; threadNum< MaxThreads; threadNum ++){
如果{
控制台(threadArray [threadNum] .IsBusy!)。的WriteLine(启动主题:{0},threadNum);
threadArray [threadNum] .RunWorkerAsync(F);
fileProcessed = TRUE;
中断;
}
}
如果{
Thread.sleep代码(50)(fileProcessed!);
中断;
}
}
}
}
私人无效的button1_Click(对象发件人,EventArgs五){
assignmentWorker.RunWorkerAsync();
}
我不是很满意这个答案,因为我不知道为什么,确切地说,它不工作,你最初的设计吧。也许别人可以回答这个问题......? 。至少这将让你一个工作版本
编辑:您原来的版本没有工作,因为 BackgroundWorkerFilesRunWorkerCompleted
同一个线程的button1_Click
(UI线程)上运行。既然你不释放在UI线程,线程永远不会标示为完成。
I am trying to setup multiple BackgroundWorker
s to do work and when not busy start doing the next bit of work. I can't seem to get them working properly. I have the below code.
When I set FilesToProcess
equal or less than MaxThreads
it works perfectly although if I make it higher, the app freezes.
I am sure it is something simple, but I just can't see it.
Thanks for any help :)
Jay
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace bgwtest
{
public partial class Form1 : Form
{
private const int MaxThreads = 20;
private const int FilesToProcess = 21;
private BackgroundWorker[] threadArray = new BackgroundWorker[MaxThreads];
public Form1()
{
InitializeComponent();
}
private void Form1Load(object sender, EventArgs e)
{
InitializeBackgoundWorkers();
}
private void InitializeBackgoundWorkers()
{
for (var f = 0; f < MaxThreads; f++)
{
threadArray[f] = new BackgroundWorker();
threadArray[f].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork);
threadArray[f].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted);
threadArray[f].WorkerReportsProgress = true;
threadArray[f].WorkerSupportsCancellation = true;
}
}
private void button1_Click(object sender, EventArgs e)
{
for (var f = 0; f < FilesToProcess; f++)
{
var fileProcessed = false;
while (!fileProcessed)
{
for (var threadNum = 0; threadNum < MaxThreads; threadNum++)
{
if (!threadArray[threadNum].IsBusy)
{
Console.WriteLine("Starting Thread: {0}", threadNum);
threadArray[threadNum].RunWorkerAsync(f);
fileProcessed = true;
break;
}
}
if (!fileProcessed)
{
Thread.Sleep(50);
}
}
}
}
private void BackgroundWorkerFilesDoWork(object sender, DoWorkEventArgs e)
{
ProcessFile((int)e.Argument);
e.Result = (int)e.Argument;
}
private static void ProcessFile(int file)
{
Console.WriteLine("Processing File: {0}", file);
}
private void BackgroundWorkerFilesRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
Console.WriteLine("Processed File: {0}", (int)e.Result);
}
}
}
The problem appears to be that your workers are never completing. Why this is, I'm not sure; it has something to do with the fact that the method (and thread) you are running them from is not itself completing. I was able to solve the problem by creating another worker to assign files to the worker array:
private BackgroundWorker assignmentWorker;
private void InitializeBackgoundWorkers() {
assignmentWorker = new BackgroundWorker();
assignmentWorker.DoWork += AssignmentWorkerOnDoWork;
// ...
}
private void AssignmentWorkerOnDoWork( object sender, DoWorkEventArgs doWorkEventArgs ) {
for( var f = 0; f < FilesToProcess; f++ ) {
var fileProcessed = false;
while( !fileProcessed ) {
for( var threadNum = 0; threadNum < MaxThreads; threadNum++ ) {
if( !threadArray[threadNum].IsBusy ) {
Console.WriteLine( "Starting Thread: {0}", threadNum );
threadArray[threadNum].RunWorkerAsync( f );
fileProcessed = true;
break;
}
}
if( !fileProcessed ) {
Thread.Sleep( 50 );
break;
}
}
}
}
private void button1_Click( object sender, EventArgs e ) {
assignmentWorker.RunWorkerAsync();
}
I'm not happy with this answer because I don't know why, exactly, it didn't work as you originally designed it. Perhaps someone else can answer that...? At least this will get you a working version.
EDIT: Your original version didn't work because the BackgroundWorkerFilesRunWorkerCompleted
runs on the same thread as button1_Click
(the UI thread). Since you are not freeing up the UI thread, the thread is never getting marked as complete.
这篇关于C#多BackgroundWorkers的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!