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 交互,除非 OverviewDetailed UI 组件)应该在 DoWork 内部发生。