C'è un comportamento che non mi è chiaro del BackgroundWorker: in alcuni casi, durante l'esecuzione sembra che la Form non risponda più al click del mouse.
Nel mio esempio ho un BackgroundWorker che viene avviato dal tasto Start e che può essere interrotto dal tasto Stop.
Apparentemente funziona tutto, però se all'interno di ProgressChanged faccio cose troppo complicate, allora la Form sembra
che non risponda più e quindi non posso neppure premere il tasto Stop per interrompere il BackgroundWorker.
In realtà, ho anche trovato un modo per farlo comunque funzionare: inserendo all'interno del DoWork una istruzione:
System.Threading.Thread.Sleep(MsSleep);
con un MsSleep abbastanza alto, in questo modo tutto funziona.
Premesso che che all'interno di ProgressChanged sarebbe bene fare poche cose, comunque a me il comportamento mi sembra un po' strano, forse sbaglio io qualche cosa?
Per simulare il problema, ho fatto un piccolo programma con 2 variabili:
MsSleep per impostare i millisecondi dello sleep
NumLoop per simulare delle operazioni complicate all'interno di ProgressChanged
I risultati sono:
//MsSeep=1 NumLoop=100 ok
//MsSeep=1 NumLoop=1000 La Form non risponde al click
//MsSeep=100 NumLoop=1000 ok
qui il programma di esempio:
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;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged);
this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
}
private int MsSleep = 100;
private int NumLoop = 1000;
//MsSeep=1 NumLoop=100 ok
//MsSeep=1 NumLoop=1000 La Form non risponde al click
//MsSeep=100 NumLoop=1000 ok
private void Form1_Load(object sender, EventArgs e)
{
this.backgroundWorker1.WorkerReportsProgress = true;
this.backgroundWorker1.WorkerSupportsCancellation = true;
}
private void button_Start_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void button_Stop_Click(object sender, EventArgs e)
{
backgroundWorker1.CancelAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int i_max = 10000;
for (int i = 1; i< i_max; i++)
{
double pd = (double)i / (double)i_max*100;
int pi = (int)pd;
backgroundWorker1.ReportProgress(pi);
if (backgroundWorker1.CancellationPending) break;
System.Threading.Thread.Sleep(MsSleep);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
for (int i = 1; i < NumLoop; i++)
{
this.Text = e.ProgressPercentage.ToString() + " " + DateTime.Now.Millisecond.ToString();
}
this.Refresh();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.Text = "OK";
}
}
}