2012-07-12 6 views
3

У меня есть форма WPF, содержащая кнопку и элемент индикатора выполнения. Когда я нажимаю кнопку, она вызывает функцию из другого класса, которая начинает работника фона, который отвечает за чтение/запись данных через последовательный порт на устройство, для которого я программирую интерфейс Windows.ProgressBar не обновляется

Раньше я использовал новую тему, но я решил попробовать фона рабочего, но все равно не повезло.

Что происходит, я нажимаю на кнопку, и индикатор не остается на уровне 0% до моей трудоёмки (10+ секунд) для цикла завершен, а затем прогресс подскакивает до 100%

любой помощь , заранее спасибо. Ниже приведен код для моего интерфейса логики:

private void connectButton_Click(object sender, RoutedEventArgs e) //Connect button clicked 
    { 
     if (!Global.isConnected) 
     { 
      device.readValues((string)portsOpen.SelectedValue, connectProgress); 

      portsOpen.IsEnabled = false; 
      connectButton.Content = "Disconnect"; 
     } 
     else 
     { 
      device.disconnect(); 

      portsOpen.IsEnabled = true; 
      connectButton.Content = "Connect"; 
     } 
    } 

и ниже код для моего дополнительного класса:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO.Ports; 
using System.Windows.Controls; 
using System.ComponentModel; 

namespace lookoutSecurity 
{ 
    class agentRadioRead 
    { 
    /*Local Variable Declarations*/ 
    SerialPort sp; 
    BackgroundWorker worker; 
    int attempt = 0; 

    public string[] populateAvailablePorts() //Returns string array of open ports 
    { 
     String[] portsAvailable = SerialPort.GetPortNames(); 
     return portsAvailable; 
    } 

    public void readValues(string selectedPort, ProgressBar progressBar) //Function that sets up serial port and background worker 
    { 
     sp = new SerialPort(selectedPort, 9600, Parity.None, 8, StopBits.One); 

     worker = new BackgroundWorker(); 
     worker.WorkerReportsProgress = true; 
     worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
     worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged); 
     worker.RunWorkerAsync(progressBar); 
    } 

    private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) //Update user interface with current percentage 
    { 
     ProgressBar progressBar = e.UserState as ProgressBar; 

     App.Current.Dispatcher.Invoke(
      System.Windows.Threading.DispatcherPriority.Send, 
       new Action(
        delegate() 
        { progressBar.Value = e.ProgressPercentage; })); 
    } 

    private void worker_DoWork(object sender, DoWorkEventArgs e) //Initial starting point for reading data 
    { 
     startRead((ProgressBar)e.Argument); 
    } 

    private string sendInitial() //Sends ? and returns init ASUTTON 
    { 
     string init = ""; 
     sp.Write("?"); 

     for (int i = 0; i < 7; i++) 
     { 
      try 
      { 
       init += sp.ReadByte().ToString(); 
      } 
      catch 
      { 
       break; 
      } 
     } 

     return init; 
    } 

    private void startRead(ProgressBar progressBar) //Initializes data send and receive 
    { 
     sp.ReadTimeout = 5000; 
     sp.Open(); 

     string init = sendInitial(); 

     if (init == Global.AGENT_RADIO) 
     { 
      sp.Write(Global.READ_VALUES, 0, Global.READ_VALUES.Length); 

      byte key = (byte)sp.ReadByte(); 

      if (Global.START_COMMAND == key) 
      { 
       for (int i = 1; i < 2247; i++) 
       { 
        object progressBarObject = new object(); 
        progressBarObject = progressBar; 
        int progress = (i/2246) * 100; 
        worker.ReportProgress(progress, progressBarObject); 

        readData(i, progressBar); 
        sp.Write(Global.GO_AHEAD, 0, Global.GO_AHEAD.Length); 

        sp.DiscardInBuffer(); 
        sp.DiscardOutBuffer(); 
       } 
      } 
      else 
      { 
       System.Windows.MessageBox.Show("Connection Failed - Invalid Key: " + key); 
       sp.Close(); 
      } 
     } 
     else 
     { 
      sp.Close(); 

      if (attempt < 3) 
      { 
       attempt++; 
       startRead(progressBar); 
      } 
      else 
      { 
       System.Windows.MessageBox.Show("Connection Failed - Not Agent Radio: " + init); 
      } 
     } 
    } 

    private void readData(int iteration, ProgressBar progress) //Reads data for current iteration 
    { 
     byte value = 0; 

     try 
     { 
      value = (byte)sp.ReadByte(); 
     } 
     catch 
     { 
      sp.Close(); 
      Global.isConnected = false; 

      if (attempt < 3) 
      { 
       attempt++; 
       startRead(progress); 
      } 
      else 
      { 
       System.Windows.MessageBox.Show("Read Timeout - Value Number: " + iteration); 
       App.Current.Shutdown(); 
      } 
     } 

     if (iteration > 0 && iteration < 385) //read schedule 
     { 
      double pos = (iteration - 1)/48; 

      int i = (int)Math.Floor(pos); 
      int j = (iteration - 1) - (i * 48); 

      Live.schedule[i, j] = value; 
     } 

     if (iteration > 384 && iteration < 1285) //read alarm history 
     { 
      double pos = (iteration - 385)/9; 

      int i = (int)Math.Floor(pos); 
      int j = (iteration - 385) - (i * 9); 

      Live.alarms[i, j] = value; 
     } 

     if (iteration > 1284 && iteration < 1345) //read error log 
     { 
      double pos = (iteration - 1285)/6; 

      int i = (int)Math.Floor(pos); 
      int j = (iteration - 1285) - (i * 6); 

      Live.errors[i, j] = value; 
     } 

     if (iteration > 1344 && iteration < 1945) //read voltage history 
     { 
      double pos = (iteration - 1345)/6; 

      int i = (int)Math.Floor(pos); 
      int j = (iteration - 1345) - (i * 6); 

      Live.voltage[i, j] = value; 
     } 

     if (iteration > 1944 && iteration < 1973) //read holidays 
     { 
      Live.holidays[iteration - 1945] = value; 
     } 

     if (iteration > 1972 && iteration < 2168) //read message sequences 
     { 
      double pos = (iteration - 1973)/15; 

      int i = (int)Math.Floor(pos); 
      int j = (iteration - 1973) - (i * 15); 

      Live.messages[i, j] = value; 
     } 

     if (iteration > 2167 && iteration < 2196) //read message info 
     { 
      Live.recordings[iteration - 2168] = value; 
     } 

     if (iteration > 2195 && iteration < 2246) //read sysval 
     { 
      Live.sysval[iteration - 2196] = value; 
     } 

     if (iteration == 2246 && value == Global.FINISH_COMMAND) 
     { 
      System.Windows.MessageBox.Show("All values from the device have been received.", "Data Received", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information); 

      Global.isConnected = true; 
     } 
    } 

    public void disconnect() //Disconnects device 
    { 
     if (Global.isConnected == true) 
     { 
      sp.Write(Global.EXIT_PROGRAM, 0, Global.EXIT_PROGRAM.Length); 
      Global.isConnected = false; 
     } 
    } 
} 
} 
+0

Возможно, вы захотите использовать '(ProgressBar) e.UserState' вместо' e.UserState as ProgressBar'. Оператор 'as' является caryover из VB.NET и IMHO не должен использоваться в C# ... –

+2

@ColeJohnson Можете ли вы объяснить свои аргументы, почему' as' не следует использовать в C#? – dlras2

+1

@ColeJohnson: В этом нет ничего плохого. Это отличный C#. –

ответ

3

Ваша проблема здесь:

int progress = (i/2246) * 100; 

я/2246 даст int, который будет усечен до нуля (поскольку i работает от 0 до < 2246), который * 100 дает нуль. Пока ваша петля не закончится, когда i = 2246 и 2246/2446 * 100 = 100.

Я упал за это перед собой. Вам нужно включить i в float (или double), чтобы он выполнял деление с плавающей запятой вместо целочисленного деления. Затем вам нужно будет вернуть все обратно в int, поскольку прогресс - это int.

Что-то вроде:

int progress = (int)((float)i/2246.0) * 100; 
+1

'int progress = (int) ((float) i/2246.0) * 100;' должно быть 'int progress = (int) (((float) i/2246.0) * 100); 'иначе он все равно даст тот же результат' 0' – GETah

+2

Как насчет просто 100 * i/2246?(язык в щеке) – Alan

+0

Почему бы не использовать 'double'? Более точность == более точные ответы. –

3

То есть в основном по следующим причинам:

int progress = (i/2246) * 100; 

прогресс не всегда 0 до i>2246, и именно поэтому вы получите значение прогресса в 0 до последнего цикла итерации, где прогресс равен 1*100=100

Вы должны сделать это вместо этого :

int progress = (int)(((double) i/2246.0) * 100); 
+1

Думайте, что вам не хватает окончательного отбрасывания обратно в int! –

+1

Несомненно, никаких проблем. Просто осознал это и обновил свой ответ :) – GETah

+0

Спасибо за помощь –

Смежные вопросы