gpt4 book ai didi

c# - 在另一个 BackgroundWorker 中运行一个 BackgroundWorker

转载 作者:太空狗 更新时间:2023-10-29 22:08:36 26 4
gpt4 key购买 nike

我正在尝试在项目中执行数据库密集型任务。这是一个演练:

我们需要搜索我们的 worker 数据库,我们称之为 Locums,并找到一个适合特定工作的人。当我们决定处理 x 个作业时,此过程开始。因此,在单击按钮时,我们使用 ProcessJobBatch() 方法进行处理。然而,这种方法只能针对非常有限数量的 Locums 进行处理。因此填满调度程序控件需要不到 10 秒的时间。现在,一旦提供了有限数量的 Locums,我们需要运行后台任务来检查其余的 Locums。大约有 1250 个!

因此,一旦 ProcessJobBatch() 完成,BackgroundWorkerBackgroundWorkerMoreLocums 就会关闭。现在,这个 worker 基本上做了一个简单的循环:对于每个工作,遍历整个 1250 名员工。这花费的时间太长了。我需要使用我无法使用 ATM 的替代策略来计划它,或者我需要为内部 for-each 循环显示辅助进度条。

更多说明:我们每天多次导入一批工作(10 到 70)。导入批处理后,应用程序会指示登录用户“首选查找”那些新创建的作业。用户已经有一个他最喜欢的位置列表(1 到 20)。他想先把工作分配给他最喜欢的人。这是通过 ProcessJobBatch() 完成的。但是,有两种情况会阻止那里的流量:

  • 如果某些工作没有下降怎么办有什么喜欢的地方吗?
  • 如果整体有一个地方怎么办几乎可以做所有工作的DB因为他不受欢迎?

所以,我最终得到了一个为每个 Locum 匹配工作的场景。

问题:第二个 BackgroundWorker 可以在 BackgroundWorker 的 DoWork 中运行吗?我第二次扫描错了吗?

环境:Windows 7 Pro 64 位、Visual Studio 2010、C#、.NET 4.0 和 Windows 窗体

    private void ButtonPreferenceFind_Click(object sender, EventArgs e) {
if (LookUpBatches.EditValue != null) {
JobBatch JobBatchSelected = DbContext.JobBatches.FirstOrDefault(job_batch=> job_batch.OID == LookUpBatches.EditValue.ToString());

if (JobBatchSelected != null && JobBatchSelected.Jobs.Count(condition => condition.JobStatusID == 1) > 0) {
if (XtraMessageBox.Show(String.Format("Are you sure to process {0} job(s)?", JobBatchSelected.Jobs.Count(condition => condition.JobStatusID == 1)), Text, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) {
ProcessJobBatch(JobBatchSelected);

IEnumerable<Job> SpecificJobs = from req_jobs in JobBatchSelected.Jobs
where req_jobs.JobStatusID == 1
select req_jobs;

ProgressBarControlPreferenceFinder.EditValue = 0;
ProgressBarControlPreferenceFinder.Properties.Minimum = 0;
ProgressBarControlPreferenceFinder.Properties.Maximum = SpecificJobs.Count() - 1;

BackgroundWorkerMoreLocums.RunWorkerAsync(SpecificJobs);

} else {
LookUpBatches.Focus();
}

} else {
XtraMessageBox.Show("Unable to retrieve the selected batch or the batch has no processable jobs.", Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
LookUpBatches.Focus();

}

} else {
XtraMessageBox.Show("Select a batch first.", Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
LookUpBatches.Focus();

}
}

#region Background Searching
private void BackgroundWorkerMoreLocums_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) {
try {
e.Result = GetTableData(e.Argument);

}
catch (Exception ex) {
XtraMessageBox.Show("Background Error: " + ex.Message, "Excite Engine 2", MessageBoxButtons.OK, MessageBoxIcon.Error);
e.Result = ex;
}
}

private void BackgroundWorkerMoreLocums_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) {
// only display progress, do not assign it to grid
ProgressBarControlPreferenceFinder.Increment(e.ProgressPercentage);
}

private void BackgroundWorkerMoreLocums_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) {
if (e.Result is DataTable) {
//dataGridView1.DataSource = e.Result as DataTable;
}
else if (e.Result is Exception) {
}
}

private DataTable GetTableData(Object JobList) {
DataTable ResultDataTable = new DataTable();
ResultDataTable.Columns.Add();


IEnumerable<Job> JobBatchSelected = (IEnumerable<Job>)JobList;

IEnumerable<Locum> LeftOverLocums = from lefties in DbContext.Locums
//where SchedulerMatrixStorage.Resources.Items.Select(res => (long)res.Id).ToList().Contains(lefties.OID) == false
select lefties;

int NumOfJobsProcessed = 0;

List<KeyValuePair<long, TemporaryPreferenceFindLocum>> AlreadyPrefferedLocums = new List<KeyValuePair<long, TemporaryPreferenceFindLocum>>();

foreach (Job oneJob in JobBatchSelected) {

foreach (Locum oneLocum in LeftOverLocums) {

if (DbContext.Availabilities.Any(check => check.LocumID == oneLocum.OID && check.AvailableDate == oneJob.JobDate && check.AvailabilityStatusID == 1)) {
//This Locum can do this job

//Now check if he/she has been just alloted
if (AlreadyPrefferedLocums.Any(search => search.Key == oneLocum.OID && search.Value.JobDate == oneJob.JobDate) == false) {
//No? Cool!
//Add to the list to prevent double allocation
AlreadyPrefferedLocums.Add(new KeyValuePair<long, TemporaryPreferenceFindLocum>(oneJob.OID, new TemporaryPreferenceFindLocum(oneJob.JobDate, oneJob.OID, oneLocum.OID, oneLocum.FirstName + " " + oneLocum.LastName)));

}
else {
continue;

}

}
else {
//Not marked as Avaliable on the required job date...
continue;

}

}

NumOfJobsProcessed++;
BackgroundWorkerMoreLocums.ReportProgress((int)(NumOfJobsProcessed * 100F / (JobBatchSelected.Count() - 1)));
}

return ResultDataTable;
}
#endregion

最佳答案

A BackgroundWorker可以从 DoWork 中开始另一个处理程序 BackgroundWorker ,但您需要了解使用此类方案的后果。当您从主 UI 线程启动后台工作程序时,DoWork处理程序在线程池线程上执行,而 ProgressChangedRunWorkerCompleted在主 UI 线程上执行,使您可以安全地与 Windows 窗体控件进行交互。

当您从主 UI 线程启动 worker 时,这种情况是有保证的,因为它会获取 SynchronizationContext在该线程上可用,并由 Windows 窗体基础结构初始化。

但是,当您从 DoWork 启动后台工作程序时另一个工作人员的处理程序,您将从缺少导致 ProgressChanged 的同步上下文的线程池线程启动它和 RunWorkerCompleted处理程序也将在线程池线程上执行,而不是在您的主 UI 线程中执行,这使得您从这些处理程序中与 Windows 窗体控件进行交互是不安全的。

关于c# - 在另一个 BackgroundWorker 中运行一个 BackgroundWorker,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5244568/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com