Je suis nouveau travail avec un travailleur de fond en C#. Voici une classe, et en dessous, vous trouverez la instansiation de celui-ci, et là-dessous je définirai mon problème pour vous:c travailleur de fond # de OpenNETCF - e.result donne une ObjectDisposedException
Je le dessin de la classe:
class Drawing
{
BackgroundWorker bgWorker;
ProgressBar progressBar;
Panel panelHolder;
public Drawing(ref ProgressBar pgbar, ref Panel panelBig) // Progressbar and panelBig as reference
{
this.panelHolder = panelBig;
this.progressBar = pgbar;
bgWorker = new BackgroundWorker();
bgWorker.WorkerReportsProgress = true;
bgWorker.WorkerSupportsCancellation = true;
bgWorker.DoWork += new OpenNETCF.ComponentModel.DoWorkEventHandler(this.bgWorker_DoWork);
bgWorker.RunWorkerCompleted += new OpenNETCF.ComponentModel.RunWorkerCompletedEventHandler(this.bgWorker_RunWorkerCompleted);
bgWorker.ProgressChanged += new OpenNETCF.ComponentModel.ProgressChangedEventHandler(this.bgWorker_ProgressChanged);
}
public void createDrawing()
{
bgWorker.RunWorkerAsync();
}
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
Panel panelContainer = new Panel();
// Adding panels to the panelContainer
for(i=0; i<100; i++)
{
Panel panelSubpanel = new Panel();
// Setting size, color, name etc....
panelContainer.Controls.Add(panelSubpanel); // Adding the subpanel to the panelContainer
//Report the progress
bgWorker.ReportProgress(0, i); // Reporting number of panels loaded
}
e.Result = panelContainer; // Send the result(a panel with lots of subpanels) as an argument
}
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar.Value = (int)e.UserState;
this.progressBar.Update();
}
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error == null)
{
this.panelHolder = (Panel)e.Result;
}
else
{
MessageBox.Show("An error occured, please try again");
}
}
}
Instansiating un objet de cette classe:
public partial class Draw: Form
{
public Draw()
{
ProgressBar progressBarLoading = new ProgressBar();
// Set lots of properties on progressBarLoading
Panel panelBigPanelContainer = new Panel();
Drawing drawer = new Drawing(ref progressBarLoading, ref panelBigPanelContainer);
drawer.createDrawing(); // this makes the object start a new thread, loading all the panels into a panel container, while also sending the progress to this progressbar.
}
}
Voici mon problème: Dans le vide privé bgWorker_RunWorkerCompleted (expéditeur d'objet, RunWorkerCompletedEventArgs e)
Je ne reçois pas le résultat comme il se doit. Quand je regarde le débogage et le e.Result, les propriétés du panneau ont ce message d'exception:
'((System.Windows.Forms.Control)(e.Result)).ClientSize' threw an exception of type 'System.ObjectDisposedException'
Ainsi, l'objet se placé, mais « pourquoi » est ma question, et comment puis-je résoudre ce problème?
J'espère que quelqu'un va me répondre, cela me rend fou. Une autre question que j'ai: Est-il permis d'utiliser "ref" avec des arguments? est-ce une mauvaise programmation?
Merci d'avance.
J'ai aussi écrit comment je comprends le travailleur de fond ci-dessous ici:
Ce que je pense est les "règles" pour les travailleurs de fond:
bgWorker.RunWorkerAsync(); => starts a new thread.
bgWorker_DoWork cannot reach the main thread without delegates
-
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
// The work happens here, this is a thread that is not reachable by
the main thread
e.Result => This is an argument which can be reached by
bgWorker_RunWorkerCompleted()
bgWorker.ReportProgress(progressVar); => Reports the progress to the
bgWorker_ProgressChanged()
}
-
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// I get the progress here, and can do stuff to the main thread from here
(e.g update a control)
this.ProgressBar.Value = e.ProgressPercentage;
}
-
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// This is where the thread is completed.
// Here i can get e.Result from the bgWorker thread
// From here i can reach controls in my main thread, and use e.Result in my main thread
if (e.Error == null)
{
this.panelTileHolder = (Panel)e.Result;
}
else
{
MessageBox.Show("There was an error");
}
}
J'espérais pas entrer dans d'invoquer, mais il semble que je dois le faire de cette façon .... – Ikky