C# 应用程序后台工作者 - Thread.Sleep 停止 UI
C# application background worker - Thread.Sleep stops UI
我正在制作一个 C# 应用程序来监视 SQL 中的一些内容。我使用后台工作人员获取 SQL 数据,然后根据这些数据构建一些图表。很基本。然而,有一件令人沮丧的事情。在 worker 中使用 Thread.Sleep 会完全锁定 UI。没有加载 gif,输入没有注册,nada。这对我来说是非常奇怪的行为,因为从我读到的关于后台工作者用例的内容来看,它应该 运行 在它自己的线程上,完全与 UI 分开。那么给出了什么?我可以用什么来代替这个?这是我的后台工作人员代码:
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
if (CollectionCanceled)
return;
//Get data from SQL DB
var jobService = _serviceFactory.CreateJobService();
var jobs = jobService.GetAllJobs(true);
backgroundWorker1.ReportProgress(0, jobs);
}
private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
var allJobs = e.UserState as IList<Job>;
if (allJobs == null || CollectionCanceled)
return;
//Build collection
Dictionary<string, Dictionary<string, int>> details = new Dictionary<string, Dictionary<string, int>>();
foreach (var job in allJobs)
{
var overViewKey = job.State.ToString();
var detailKey = string.Format("{0} ({1})", job.Name, job.Type);
if (!details.ContainsKey(overViewKey))
details.Add(overViewKey, new Dictionary<string, int>());
if (!details[overViewKey].ContainsKey(detailKey))
details[overViewKey].Add(detailKey, 0);
details[overViewKey][detailKey]++;
}
//Build charts
Overview.Series.Clear();
Detailed.Series.Clear();
Overview.Series.Add("Jobs");
Detailed.Series.Add("Jobs");
foreach (var runniningOrEnqueued in details)
{
Overview.Series["Jobs"].Points.AddXY(runniningOrEnqueued.Key, runniningOrEnqueued.Value.Count);
foreach (var jobDetail in runniningOrEnqueued.Value)
Detailed.Series["Jobs"].Points.AddXY(jobDetail.Key, jobDetail.Value);
}
//Stop for however many secs the user specified
Thread.Sleep((int)TimeSpan.FromSeconds(WaitTimer).TotalMilliseconds);
}
private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (!CollectionCanceled)
{
ExecuteBackGroundWork();
}
else
{
CollectionCanceled = false;
}
}
private void ExecuteBackGroundWork()
{
backgroundWorker1.RunWorkerAsync();
}
BackgroundWorker_ProgressChanged
不会发生在工作线程上,它发生在 UI 线程上。只有 BackgroundWorker_DoWork
内发生的代码在工作线程上是 运行。
您在 ProgressChanged 中所做的大部分工作(如果不是全部,我没有在您的代码中看到任何明确的 UI 交互,除非 Overview
和 Detailed
UI 组件)应该在 DoWork 内部发生。
我正在制作一个 C# 应用程序来监视 SQL 中的一些内容。我使用后台工作人员获取 SQL 数据,然后根据这些数据构建一些图表。很基本。然而,有一件令人沮丧的事情。在 worker 中使用 Thread.Sleep 会完全锁定 UI。没有加载 gif,输入没有注册,nada。这对我来说是非常奇怪的行为,因为从我读到的关于后台工作者用例的内容来看,它应该 运行 在它自己的线程上,完全与 UI 分开。那么给出了什么?我可以用什么来代替这个?这是我的后台工作人员代码:
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
if (CollectionCanceled)
return;
//Get data from SQL DB
var jobService = _serviceFactory.CreateJobService();
var jobs = jobService.GetAllJobs(true);
backgroundWorker1.ReportProgress(0, jobs);
}
private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
var allJobs = e.UserState as IList<Job>;
if (allJobs == null || CollectionCanceled)
return;
//Build collection
Dictionary<string, Dictionary<string, int>> details = new Dictionary<string, Dictionary<string, int>>();
foreach (var job in allJobs)
{
var overViewKey = job.State.ToString();
var detailKey = string.Format("{0} ({1})", job.Name, job.Type);
if (!details.ContainsKey(overViewKey))
details.Add(overViewKey, new Dictionary<string, int>());
if (!details[overViewKey].ContainsKey(detailKey))
details[overViewKey].Add(detailKey, 0);
details[overViewKey][detailKey]++;
}
//Build charts
Overview.Series.Clear();
Detailed.Series.Clear();
Overview.Series.Add("Jobs");
Detailed.Series.Add("Jobs");
foreach (var runniningOrEnqueued in details)
{
Overview.Series["Jobs"].Points.AddXY(runniningOrEnqueued.Key, runniningOrEnqueued.Value.Count);
foreach (var jobDetail in runniningOrEnqueued.Value)
Detailed.Series["Jobs"].Points.AddXY(jobDetail.Key, jobDetail.Value);
}
//Stop for however many secs the user specified
Thread.Sleep((int)TimeSpan.FromSeconds(WaitTimer).TotalMilliseconds);
}
private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (!CollectionCanceled)
{
ExecuteBackGroundWork();
}
else
{
CollectionCanceled = false;
}
}
private void ExecuteBackGroundWork()
{
backgroundWorker1.RunWorkerAsync();
}
BackgroundWorker_ProgressChanged
不会发生在工作线程上,它发生在 UI 线程上。只有 BackgroundWorker_DoWork
内发生的代码在工作线程上是 运行。
您在 ProgressChanged 中所做的大部分工作(如果不是全部,我没有在您的代码中看到任何明确的 UI 交互,除非 Overview
和 Detailed
UI 组件)应该在 DoWork 内部发生。