2015-05-03 4 views
0

Я делаю приложение C# для мониторинга некоторых вещей в SQL. Я использую фонового работника для сбора данных SQL, а затем создаю несколько диаграмм на основе данных. Довольно простой. Однако в этом есть одна неприятная вещь. Использование Thread.Sleep в рабочем состоянии полностью блокирует пользовательский интерфейс. Нет загрузки gif, входы не регистрируются, нада. Это очень странное поведение для меня, потому что из того, что я читал о случаях использования фонового рабочего, он должен работать на своем потоке, ПОЛНОСТЬЮ отдельно от пользовательского интерфейса. Так что же дает? Что я могу использовать вместо этого? Вот мой код фона рабочий:C# appliction background worker - Thread.Sleep stops 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(); 
    } 

ответ

4

BackgroundWorker_ProgressChanged не происходит на рабочем потоке, это происходит в потоке пользовательского интерфейса. В рабочем потоке запускается только код, который происходит внутри BackgroundWorker_DoWork.

Большая часть работы, которую вы делаете внутри ProgressChanged (если не все, я не вижу явного взаимодействия пользовательского интерфейса в коде, если Overview и Detailed не UI componets) должно происходить внутри DoWork.

+0

Причина, по которой BackgroundWorker_ProgressChanged происходит в потоке пользовательского интерфейса, заключается в том, что вы можете обновлять элементы управления в пользовательском интерфейсе. –

+0

duh! Теперь я чувствую себя глупо. Спасибо, что помогли приложению n00b. Отметьте как ответ, как только я смогу. – user2326106