C# Несколько BackgroundWorkers
Я пытаюсь настроить несколько BackgroundWorker
s, чтобы сделать работу, и когда не занят, начните делать следующий бит работы. Я не могу заставить их работать как следует. У меня есть код ниже.
когда я поставил FilesToProcess
равно или меньше MaxThreads
он отлично работает, хотя, если я сделаю его выше, приложение замерзнет.
Я уверен, что это что-то простое, но я просто не могу видеть это.
Спасибо за любую помощь :)
Джей
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);
}
}
}
1 ответов
проблема заключается в том, что ваши работники никогда не завершают. Почему это так, я не уверен; это связано с тем, что метод (и поток), из которого вы их запускаете, сам по себе не завершается. Я смог решить проблему, создав другого работника для назначения файлов рабочему массиву:
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();
}
Я не доволен этим ответом, потому что я не знаю, почему именно, он не работал так, как вы изначально его разработали. Возможно, кто-то другой сможет ответить. что...? По крайней мере, это даст вам рабочую версию.
EDIT: ваша оригинальная версия не работала, потому что BackgroundWorkerFilesRunWorkerCompleted
выполняется в том же потоке, как button1_Click
(поток пользовательского интерфейса). Поскольку вы не освобождаете поток пользовательского интерфейса, поток никогда не помечается как полный.