J'ai un GridControl
que je remplis en utilisant un BackgroundWorker
. Ensuite, j'utilise un autre BackgroundWorker
pour effectuer des calculs sur l'ensemble de données qui est la source de données du GridControl
. Comme j'essaye de faire ceci une opération croisée sur l'erreur GridControl
est jetée. Je suis incapable de comprendre que, malgré le fait de ne pas effectuer d'opération sur le contrôle de la grille lui-même, comment l'erreur est générée. (J'utilise DevExpress, mais cela ne devrait pas changer le concept).Travailler avec la grille en utilisant BackgroundWorker
Je peux également utiliser un BackgroundWorker
pour effectuer un travail différent, c'est-à-dire rendre ce code plus efficace.
Voici mon code: -
public partial class MainForm : XtraForm
{
private BackgroundWorker loadworker = new BackgroundWorker();
private BackgroundWorker calcworker = new BackgroundWorker();
private AutoResetEvent resetEvent = new AutoResetEvent(false);
private Database _db = EnterpriseLibraryContainer.Current.GetInstance<Database>("ConnString");
private DataSet ds;
public MainForm()
{
InitializeComponent();
loadworker.DoWork += loadworker_DoWork;
loadworker.RunWorkerCompleted += loadworker_RunWorkerCompleted;
loadworker.ProgressChanged += loadworker_ProgressChanged;
loadworker.WorkerReportsProgress = true;
calcworker.DoWork += calcworker_DoWork;
calcworker.RunWorkerCompleted += calcworker_RunWorkerCompleted;
calcworker.ProgressChanged += calcworker_ProgressChanged;
calcworker.WorkerReportsProgress = true;
}
private void calcworker_DoWork(object sender, DoWorkEventArgs e)
{
int _cnt = 0;
foreach (DataRow dr in ds.Tables[0].Rows)
{
dr["GROSS"] = (decimal)dr["BASIC"] + (decimal)dr["HRA"] + (decimal)dr["DA"];
_cnt += 1;
}
for (int i = 0; i <= _cnt; i++)
{
Thread.Sleep(100);
calcworker.ReportProgress((100 * i)/_cnt);
}
}
private void calcworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.SetState(true);
this.MainInit();
}
private void calcworker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.pgb_DataProgress.Position = e.ProgressPercentage;
}
private void loadworker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.pgb_DataProgress.Position = e.ProgressPercentage;
}
private void loadworker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
DbCommand _cmd = _db.GetSqlStringCommand("SELECT Z.EMP_CODE,Z.BASIC,Z.DA,Z.HRA,CAST(0 AS DECIMAL) GROSS FROM Z000000001 Z");
DataSet _data = _db.ExecuteDataSet(_cmd);
for (int i = 0; i <= 10; i++)
{
Thread.Sleep(500);
loadworker.ReportProgress((100 * i)/10);
}
e.Result = _data;
}
catch (Exception ex)
{
e.Cancel = true;
}
}
private void loadworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.ds = (DataSet)e.Result;
this.gridControl1.DataSource = ds.Tables[0];
this.SetState(true);
this.MainInit();
}
private void btn_FetchData_Click(object sender, EventArgs e)
{
this.gridControl1.DataSource = null;
this.SetState(false);
loadworker.RunWorkerAsync();
}
private void SetState(bool _state)
{
this.btn_Calculate.Enabled = _state;
this.btn_ClearGrid.Enabled = _state;
this.btn_FetchData.Enabled = _state;
}
private void MainInit()
{
this.pgb_DataProgress.Position = 0;
}
private void btn_ClearGrid_Click(object sender, EventArgs e)
{
this.gridControl1.DataSource = null;
}
private void btn_Calculate_Click(object sender, EventArgs e)
{
if (this.gridControl1.DataSource == null)
{
DevExpress.XtraEditors.XtraMessageBox.Show("Data Not loaded", "Message");
return;
}
else
{
this.SetState(false);
calcworker.RunWorkerAsync();
}
}
}
Vous modifiez le DataRow depuis 'calcworker_DoWork'. Grâce à la notification de changement, votre grille sera informée et ceci est effectué à partir du même fil que le changement de ligne. C'est pourquoi le code jette une exception. Une possibilité serait de définir la ligne dans loadworker_ProgressChanged. Vous pouvez transférer les données via UserState de la méthode ReportProgress. – HCL
@HCL: Alors quelle devrait être l'approche. Dois-je mettre la source de données GridControl à zéro, puis effectuer les calculs, puis définir à nouveau la source de données. Cette méthode fonctionne mais est-ce un bon moyen ou suggérez-vous le contraire. –
La façon dont vous dites est le moyen le plus rapide car il n'y a pas de communication croisée. Cependant, l'expérience de l'utilisateur peut ne pas être si bonne si c'est une opération à long terme. Une possibilité est d'utiliser Control.Invoke comme écrit par VinayC ou d'afficher une barre de progression ou de définir les données de la ligne dans l'événement ProgressChanged. – HCL