2015-11-29 3 views
0

Я пытался обновить статус в пользовательском интерфейсе для Long Running Operating. Я создал приложение на основе демо-формы, задание имеет несколько строк, каждая строка имеет дни и значения по умолчанию в каждом столбце datagrid равна 0, как только файл вычисления вычисляет одну итерацию на один день, он обновит пользовательский интерфейс и установит 1 для этого день.Сжигание событий в цикле не обновляет пользовательский интерфейс в последовательности

Я использую потоки, делегаты и события для реализации этого, и он работает как ожидается, если я поставлю Thread.Sleep (100) между двумя вызовами событий. Если я поставлю «Thread.Sleep (100)» внутри последнего вложенного цикла, то он обновит интерфейс, как ожидалось, но как только я удалю его и запустил цикл без сна, он пропускает некоторые из столбцов в пользовательском интерфейсе и напрямую обновляет последние несколько/случайные столбцы, как вы можете видеть в прикрепленной ссылке изображения (изображение вывода моего кода без спящего потока) обновляется только последний столбец.

Если я не ошибаюсь, все события запускаются последовательно, тогда они также должны обновлять пользовательский интерфейс, но это не происходит, и я не знаю почему. Я не хочу делать это спящим, потому что у меня есть около 14 вызовов в реальном приложении для обновления статуса пользовательского интерфейса, и он будет работать под циклом, поэтому, если он поставит сон (100), это будет стоить мне много, есть ли способ сделать это без SLEEP?

Image of output of my code without thread sleep

public class Class1 : IGenerate 
{ 
    public event MessageEventHandler OnMessageSending; 
    public void LongOperationMethod(BindingList<Status> _statusData) 
    { 
     if (OnMessageSending != null) 
     { 
      MessageEventArgs me = new MessageEventArgs(); 

      /// Loop for 2-3 Weeks 
      for (; ;){ 
       /// Loop for 7 day 
       for (; ;) 
       { 
        /// Calculation on everyday 
        for (int j = 0; j != 1000; ++j) 
        { 
         // to do 
        } 

        me.weekNo = k; 
        me.DayNo = i; 
        OnMessageSending(me); 

       } 
      } 
      me.Message = "Process completed successfully..."; 
      OnMessageSending(me); 
     } 
     else 
     { 
      throw new ArgumentException("Event hasn`t been rised, so we cannot continue working."); 
     } 
    } 
} 


**UI file:** 
<pre><code> 


public partial class Form1 : Form 
     { 
      BindingList<Status> _statusData = new BindingList<Status>(); 
      delegate void StringParameterDelegate(string value); 
      Class1 cls = new Class1(); 
      public Form1() 
      { 
       InitializeComponent(); 
       labelProgress.Text = ""; 
      } 

      private void button1_Click_1(object sender, EventArgs e) 
      { 
       for (int i = 1; i <= 2; ++i) 
       { 
        _statusData.Add(new Status { Week = "Week" + i, Day1 = 0, Day2 = 0, Day3 = 0, Day4 = 0, Day5 = 0, Day6 = 0, Day7 = 0 }); 
       } 

       dataGridView1.DataSource = _statusData; 
      } 

      private void button2_Click(object sender, EventArgs e) 
      { 
       Thread t1 = new Thread(() => StartingThread(_statusData)); 
       t1.Start(); 
      } 

      void StartingThread(BindingList<Status> _statusData) 
      { 
       IGenerate generate = new Class1(); 
       generate.OnMessageSending += new MessageEventHandler(generate_OnMessageSending); 
       generate.LongOperationMethod(_statusData); 
      } 

      private void generate_OnMessageSending(MessageEventArgs e) 
      { 
       int weekNo = e.weekNo; 
       int dayNo = e.DayNo; 
       this.dataGridView1.BeginInvoke(new MethodInvoker(() => dataGridView1.Rows[e.weekNo].Cells[e.DayNo + 1].Value = 1)); 
       this.labelProgress.BeginInvoke(new MethodInvoker(() => this.labelProgress.Text = e.Message)); 

      } 
     } 
</code></pre> 

ответ

1

Похоже, что вы отправляете один и тот же экземпляр MessageEventArgs каждый раз, и только обновление, что один экземпляр на фоне потока. Это означает, что ваш обработчик событий в потоке пользовательского интерфейса получит тот же самый экземпляр MessageEventArgs, который обновляется в цикле! Когда ваш обработчик UI получит MessageEventArgs, его свойства .weekNo и .DayNo вполне могли бы быть изменены следующей итерацией цикла, поскольку они работают на отдельных потоках.

Чтобы исправить это, создайте новый экземпляр MessageEventArgs каждый раз, когда вы вызываете OnMessageSending().

Соответствующий фрагмент кода:

MessageEventArgs me = new MessageEventArgs(); 
me.weekNo = k; 
me.DayNo = i; 
OnMessageSending(me); 
Смежные вопросы