PDA

View Full Version : [C#] Problema con i thread (della serie: fra poco sclero)


s1m0_93
19-12-2010, 03:25
'Sera.
Sto provando in tutti i modi a far funzionare un semplice thread che aumenta il valore di una progress bar inserite nel form.
Questo form contiene due pulsanti e due progressbar.

Il primo di questi pulsanti serve ad aumentare manualmente una delle progressbar (l'ho inserito per controllare che fosse possibile usare l'applicazione mentre il thread fosse in esecuzione), il secondo fa partire il thread.
Il problema è il seguente: una volta che faccio partire il thread viene sollevata questa eccezzione.

Operazione cross-thread non valida: è stato eseguito l'accesso al controllo 'progressBar2' da un thread diverso da quello da cui è stata eseguita la creazione.


Se serve faccio uno screenshot.
Scusate se mi sono spiegato di merda, è tardi.
Allego il codice


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace Thread_Esercitation
{
public partial class Form1 : Form
{


delegate void AumentaBarraDel();
AumentaBarraDel AumentaBarraCallBack;


public Form1()
{
InitializeComponent();
progressBar1.Step = 5;
progressBar2.Step = 5;

AggiornamentoStato(lbl_StatoProgBar1, progressBar1);
AggiornamentoStato(lbl_StatoProgBar2, progressBar2);


AumentaBarraCallBack = new AumentaBarraDel(myThreadMethod);
}



private void btt_AumentaBarra1_Click(object sender, EventArgs e)
{
AumentaValoreBarra(lbl_StatoProgBar1, progressBar1);
}


private void btt_AumentaBarra2_Click(object sender, EventArgs e)
{

Thread myThread = new Thread(new ThreadStart(AumentaBarraCallBack));
myThread.Start();
}


// Metodi


public void AumentaValoreBarra(Label lbl_Stato, ProgressBar myProgressBar)
{
myProgressBar.PerformStep();
AggiornamentoStato(lbl_Stato, myProgressBar);
}

//il metodo qua sotto modifica delle label che sono presenti sul form e indicano a che punto è la barra, non badateci
private void AggiornamentoStato(Label lbl_Stato, ProgressBar myProgressBar)
{
if (myProgressBar.Value == 0)
lbl_Stato.Text = "Stato: Non avviato";
else if (myProgressBar.Value < 100)
lbl_Stato.Text = "Stato: Completamento in corso";
else
lbl_Stato.Text = "Stato: Finito";
}

public void myThreadMethod()
{
// MessageBox.Show("Avviato");
while (progressBar2.Value < 50)
{
AumentaValoreBarra(lbl_StatoProgBar2, progressBar2);
// System.Threading.Thread.Sleep(100);
}

}
}
}

gugoXX
19-12-2010, 12:16
Da dentro il Thread che hai fatto partire non puoi modificare direttamente la GUI.
Solo il Thread che ha creato che ha creato la form puo' modificarne l'aspetto.

Da dentro il Thread, invece che chiamare semplicemente PerformStep, devi passare attraverso un BeginInvoke, che sincronizza l'esecuzione con il Thread della GUI.

Qualcosa come:

public void AumentaValoreBarraAsync(Label lbl_Stato, ProgressBar myProgressBar)
{
BeginInvoke( new Action( ()=>
{
myProgressBar.PerformStep();
AggiornamentoStato(lbl_Stato, myProgressBar);
}));
}


Come spunto.
Meglio sarebbe migliorarlo per renderlo universale, sia che lo si chiami da un altro Thread (come il tuo caso), sia che lo si chiami dal thread della GUI.

Ma meglio ancora di tutto e' riscrivere tutto usando pattern noti che hanno il vantaggio di prescindere da questo problema.
Come MVVM per WPF.