Note that there are some explanatory texts on larger screens.

plurals
  1. POWindow interrupts serial port background worker and causes read timeout to occur
    primarykey
    data
    text
    <p>I am interfacing with a device and sending and receiving around 2000 bytes from the device using c#. I find that if I click my connect button and just let it run, the process completes 80% of the time, and 20% of the time a read time out occurs. This in and of itself is a problem.</p> <p>Additionally, if I move my windows around at all while it is reading data a read timeout occurs. I thought it may have been a priority issue, so I tried messing with the priority of the background worker and interface threads, but no luck.</p> <p>Has anyone had this happen to them before? And advice is appreciated. Below is what code is relevant, if you think you need more code let me know and I will post it as well. Thanks in advance.</p> <p>Where the functions are called from:</p> <pre><code> private void connectButton_Click(object sender, RoutedEventArgs e) //Connect button clicked { if (!Global.isConnected) { agentradioread.connect((string)portsOpen.SelectedValue, this); form.deviceConnecting(this); } else { agentradioread.disconnect(); form.deviceDisconnect(this); } } private void loadSettings_Click(object sender, RoutedEventArgs e) //Loads settings { if (Global.isConnected) { agentradioread.readValues(this); } } private void sendSettings_Click(object sender, RoutedEventArgs e) //Sends settings { if (Global.isConnected) { agentradioread.readTime(); string minutes = (Create.sysval[10].ToString().Length == 1) ? "0" + Create.sysval[10].ToString() : Create.sysval[10].ToString(); string date = Create.sysval[11].ToString() + "/" + Create.sysval[12].ToString() + "/20" + Create.sysval[13].ToString(); string time = Create.sysval[9].ToString() + ":" + minutes; MessageBoxResult result = MessageBox.Show("The current device date and time is: " + date + " " + time + "\r\nIs this time correct?", "Date &amp; Time Verification", MessageBoxButton.YesNo, MessageBoxImage.Question); if (result == MessageBoxResult.Yes) //Time is correct { Create.sysval[9] = 255; } else //Time is incorrect { dateTimeChange dateTime = new dateTimeChange(); dateTime.ShowDialog(); } agentradioread.sendValues(this); } } </code></pre> <p>The functions called:</p> <pre><code>public void connect(string selectedPort, agentRadio agentR) //Connects device and reads values { agentSerial = new SerialPort(selectedPort, 9600, Parity.None, 8, StopBits.One); connectWorker = new BackgroundWorker(); connectWorker.WorkerReportsProgress = true; connectWorker.DoWork += new DoWorkEventHandler(connectWorker_DoWork); connectWorker.ProgressChanged += new ProgressChangedEventHandler(connectWorker_ProgressChanged); connectWorker.RunWorkerAsync(agentR); } public void readTime() //Reads time into sysval locations { agentSerial.DiscardInBuffer(); agentSerial.DiscardOutBuffer(); agentSerial.Write(Global.TIME, 0, Global.TIME.Length); //begin send values loadTime(); } public void readValues(agentRadio agentR) //Read values { readWorker = new BackgroundWorker(); readWorker.WorkerReportsProgress = true; readWorker.DoWork += new DoWorkEventHandler(readWorker_DoWork); readWorker.ProgressChanged += new ProgressChangedEventHandler(readWorker_ProgressChanged); agentSerial.DiscardInBuffer(); agentSerial.DiscardOutBuffer(); readWorker.RunWorkerAsync(agentR); } public void sendValues(agentRadio agentR) //Send values { sendWorker = new BackgroundWorker(); sendWorker.WorkerReportsProgress = true; sendWorker.DoWork += new DoWorkEventHandler(sendWorker_DoWork); sendWorker.ProgressChanged += new ProgressChangedEventHandler(sendWorker_ProgressChanged); agentSerial.DiscardInBuffer(); agentSerial.DiscardOutBuffer(); sendWorker.RunWorkerAsync(agentR); } public void restoreDevice(agentRadio agentR) //Restore device to defaults { agentSerial.DiscardInBuffer(); agentSerial.DiscardOutBuffer(); agentSerial.Write(Global.RESTORE, 0, Global.RESTORE.Length); //device restore command MessageBox.Show(agentSerial.ReadByte().ToString()); try { Global.restoring = true; readValues(agentR); } catch { MessageBox.Show("Your device was restored, but a read time out occured. You need to go to the connect tab and reconnect to the device, and your settings will update.", "Device Restore Notice", MessageBoxButton.OK, MessageBoxImage.Information); } } public void disconnect() //Disconnects device { if (Global.isConnected == true) { try { agentSerial.DiscardInBuffer(); agentSerial.DiscardOutBuffer(); agentSerial.Write(Global.EXIT_PROGRAM, 0, Global.EXIT_PROGRAM.Length); } catch { //leave option to reConnect } agentSerial.Close(); Global.isConnected = false; } } /*Methods that cannot be called from elsewhere in the application*/ private void connectWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) //Updates progressbar while device is connecting { ProgressBar progressBar = e.UserState as ProgressBar; App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { progressBar.Value = e.ProgressPercentage; })); } private void connectWorker_DoWork(object sender, DoWorkEventArgs e) //Connects and read values { startRead((agentRadio)e.Argument); } private void readWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) //Alerts user when values are loaded { ProgressBar progressBar = e.UserState as ProgressBar; App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { progressBar.Value = e.ProgressPercentage; })); } private void readWorker_DoWork(object sender, DoWorkEventArgs e) //Reads values { agentRadio agentR = (agentRadio)e.Argument; App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { form.deviceReading(agentR); })); agentSerial.Write(Global.READ_VALUES, 0, Global.READ_VALUES.Length); //begin read values byte key = (byte)agentSerial.ReadByte(); if (Global.START_COMMAND == key) //Verify continue key { object progressBarObject = new object(); progressBarObject = agentR.connectProgress; for (int i = 1; i &lt; 2247; i++) //Loop through values, calling read function and updating progress bar { int progress = (int)(((float)i / 2246.0) * 100); readWorker.ReportProgress(progress, progressBarObject); try { readData(i, agentR); agentSerial.Write(Global.GO_AHEAD, 0, Global.GO_AHEAD.Length); agentSerial.DiscardInBuffer(); agentSerial.DiscardOutBuffer(); } catch { break; } } } else //Key failed and displays error { App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { form.deviceDisconnect(agentR); })); MessageBox.Show("Connection Failed, Invalid Key"); } } private void sendWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) //Alerts user when values are sent { ProgressBar progressBar = e.UserState as ProgressBar; App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { progressBar.Value = e.ProgressPercentage; })); } private void sendWorker_DoWork(object sender, DoWorkEventArgs e) //Sends values { agentRadio agentR = (agentRadio)e.Argument; App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { form.deviceSending(agentR); })); agentSerial.Write(Global.SEND_VALUES, 0, Global.SEND_VALUES.Length); //begin send values byte key = (byte)agentSerial.ReadByte(); if (Global.START_COMMAND == key) //Verify continue key { object progressBarObject = new object(); progressBarObject = agentR.connectProgress; for (int i = 1; i &lt; 659; i++) //Loops and sends data to device { int progress = (int)(((float)i / 658.0) * 100); sendWorker.ReportProgress(progress, progressBarObject); try { byte result = sendData(i, agentR); if (result != Global.GO_AHEAD[0]) { MessageBox.Show("Fatal Error"); break; } agentSerial.DiscardInBuffer(); agentSerial.DiscardOutBuffer(); } catch { break; } } } else //Key failed and displays error { App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { form.deviceDisconnect(agentR); })); MessageBox.Show("Connection Failed, Invalid Key"); } } private void loadTime() //Loads device time into sysval locations { byte key = (byte)agentSerial.ReadByte(); if (Global.START_COMMAND == key) //Verify continue key { for (int i = 0; i &lt; 5; i++) { try { byte result = (byte)agentSerial.ReadByte(); Create.sysval[9 + i] = result; } catch { Create.sysval[9 + i] = 0; } } agentSerial.ReadByte(); } agentSerial.DiscardInBuffer(); agentSerial.DiscardOutBuffer(); } private string sendInitial() //Sends a ? and returns 7 bytes of data { string handshake = ""; agentSerial.Write("?"); for (int i = 0; i &lt; 7; i++) { try { handshake += agentSerial.ReadByte().ToString(); } catch { break; } } return handshake; } private void startRead(agentRadio agentR) //Initializes data send and receive { System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Highest; App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { agentR.connectProgress.IsIndeterminate = true; })); agentSerial.ReadTimeout = 5000; agentSerial.Open(); agentSerial.DiscardInBuffer(); agentSerial.DiscardOutBuffer(); string handshake = sendInitial(); if (handshake == Global.AGENT_RADIO) //Result matches agent radio version { agentSerial.Write(Global.READ_VALUES, 0, Global.READ_VALUES.Length); //begin read values byte key = (byte)agentSerial.ReadByte(); if (Global.START_COMMAND == key) //Verify continue key { App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { agentR.connectProgress.IsIndeterminate = false; })); object progressBarObject = new object(); progressBarObject = agentR.connectProgress; for (int i = 1; i &lt; 2247; i++) //Loop through values, calling read function and updating progress bar { int progress = (int)(((float)i / 2246.0) * 100); connectWorker.ReportProgress(progress, progressBarObject); try { readData(i, agentR); agentSerial.Write(Global.GO_AHEAD, 0, Global.GO_AHEAD.Length); agentSerial.DiscardInBuffer(); agentSerial.DiscardOutBuffer(); } catch { break; } } } else //Key failed and displays error { agentSerial.Close(); App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { form.deviceDisconnect(agentR); })); MessageBox.Show("Connection Failed, Invalid Key"); } } else //Result did not match an agent radio version { agentSerial.Close(); //Closes port if (attempt &lt; 3) //Attempt to connect to device 5 times { attempt++; startRead(agentR); } else //Displays error to user if connection failed { App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { form.deviceDisconnect(agentR); })); MessageBox.Show("Connection Failed, Not Agent Radio Version"); } } } private void readData(int iteration, agentRadio agentR) //Reads data for current iteration { byte value = 0; //Current value try { value = (byte)agentSerial.ReadByte(); //Reads byte } catch { agentSerial.Close(); App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { form.deviceDisconnect(agentR); })); MessageBox.Show("Connection Failed, Read Timeout"); //Displays message if read timeout occured } if (iteration &gt; 0 &amp;&amp; iteration &lt; 385) //read schedule { double pos = (iteration - 1) / 48; int i = (int)Math.Floor(pos); int j = (iteration - 1) - (i * 48); Create.schedule[i, j] = value; } if (iteration &gt; 384 &amp;&amp; iteration &lt; 1285) //read alarm history { double pos = (iteration - 385) / 9; int i = (int)Math.Floor(pos); int j = (iteration - 385) - (i * 9); Create.alarms[i, j] = value; } if (iteration &gt; 1284 &amp;&amp; iteration &lt; 1345) //read error log { double pos = (iteration - 1285) / 6; int i = (int)Math.Floor(pos); int j = (iteration - 1285) - (i * 6); Create.errors[i, j] = value; } if (iteration &gt; 1344 &amp;&amp; iteration &lt; 1945) //read voltage history { double pos = (iteration - 1345) / 6; int i = (int)Math.Floor(pos); int j = (iteration - 1345) - (i * 6); Create.voltage[i, j] = value; } if (iteration &gt; 1944 &amp;&amp; iteration &lt; 1973) //read holidays { Create.holidays[iteration - 1945] = value; } if (iteration &gt; 1972 &amp;&amp; iteration &lt; 2168) //read message sequences { double pos = (iteration - 1973) / 15; int i = (int)Math.Floor(pos); int j = (iteration - 1973) - (i * 15); Create.messages[i, j] = value; } if (iteration &gt; 2167 &amp;&amp; iteration &lt; 2196) //read message info { Create.recordings[iteration - 2168] = value; } if (iteration &gt; 2195 &amp;&amp; iteration &lt; 2246) //read sysval { Create.sysval[iteration - 2196] = value; } if (iteration == 2246 &amp;&amp; value == Global.FINISH_COMMAND) { if (Global.restoring) { App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { form.deviceConnect(agentR); })); MessageBox.Show("Your device has been restored, and all settings from the device have been received.", "Device Restore Succesful", MessageBoxButton.OK, MessageBoxImage.Information); } else { App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { form.deviceConnect(agentR); })); Global.isConnected = true; MessageBox.Show("Your device is connected, and all settings from the device have been received.", "Data Transfer Succesful", MessageBoxButton.OK, MessageBoxImage.Information); } } } private byte sendData(int iteration, agentRadio agentR) //Sends data for current iteration { byte value = 0; //For return later if (iteration &gt; 0 &amp;&amp; iteration &lt; 51) //sysval { byte[] toWrite = new byte[1]; toWrite[0] = Create.sysval[iteration - 1]; agentSerial.Write(toWrite, 0, 1); value = (byte)agentSerial.ReadByte(); } if (iteration &gt; 50 &amp;&amp; iteration &lt; 79) //holiday { byte[] toWrite = new byte[1]; toWrite[0] = Create.holidays[iteration - 51]; agentSerial.Write(toWrite, 0, 1); value = (byte)agentSerial.ReadByte(); } if (iteration &gt; 78 &amp;&amp; iteration &lt; 463) //schedule { double pos = (iteration - 79) / 48; int i = (int)Math.Floor(pos); int j = (iteration - 79) - (i * 48); byte[] toWrite = new byte[1]; toWrite[0] = Create.schedule[i, j]; agentSerial.Write(toWrite, 0, 1); value = (byte)agentSerial.ReadByte(); } if (iteration &gt; 462 &amp;&amp; iteration &lt; 658) //message sequence { double pos = (iteration - 463) / 15; int i = (int)Math.Floor(pos); int j = (iteration - 463) - (i * 15); byte[] toWrite = new byte[1]; toWrite[0] = Create.messages[i, j]; agentSerial.Write(toWrite, 0, 1); value = (byte)agentSerial.ReadByte(); } if (iteration == 658 &amp;&amp; ((byte)agentSerial.ReadByte() == Global.FINISH_COMMAND)) //Last iteration should get finish command { App.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Send, new Action( delegate() { form.deviceConnect(agentR); })); MessageBox.Show("Your settings have been transfered succesfully to the device.", "Successful Transfer", MessageBoxButton.OK, MessageBoxImage.Information); value = 17; //Simulates GO_AHEAD character for last iteration of loop } return value; //Return character off port, should be GO_AHEAD } } </code></pre> <p>Form class:</p> <pre><code>public string[] populateAvailablePorts() //Returns string array of open ports { String[] portsAvailable = SerialPort.GetPortNames(); return portsAvailable; } public void deviceConnect(agentRadio agentR) //Adjusts display for when device is disconnected { agentR.portsOpen.IsEnabled = false; agentR.connectButton.Content = "Disconnect"; agentR.connectButton.IsEnabled = true; agentR.connectProgress.Value = 100; agentR.loadSettingsConnect.Content = "Load Settings"; agentR.sendSettingsConnect.Content = "Send Settings"; agentR.loadSettingsConnect.IsEnabled = true; agentR.sendSettingsConnect.IsEnabled = true; agentR.DeviceRestore.IsEnabled = true; agentR.VoltageStack.Children.Clear(); agentR.ErrorStack.Children.Clear(); agentR.Events.Children.Clear(); agentR.DeviceRestore.IsEnabled = true; display.setDisplay(agentR); } public void deviceConnecting(agentRadio agentR) //Adjusts display for when device is disconnected { agentR.portsOpen.IsEnabled = false; agentR.connectButton.Content = "Connecting..."; agentR.connectButton.IsEnabled = false; agentR.loadSettingsConnect.IsEnabled = false; agentR.sendSettingsConnect.IsEnabled = false; agentR.DeviceRestore.IsEnabled = false; } public void deviceReading(agentRadio agentR) //Adjusts display for when device is disconnected { agentR.connectButton.IsEnabled = false; agentR.loadSettingsConnect.Content = "Reading Data..."; agentR.loadSettingsConnect.IsEnabled = false; agentR.sendSettingsConnect.IsEnabled = false; agentR.DeviceRestore.IsEnabled = false; } public void deviceSending(agentRadio agentR) //Adjusts display for when device is disconnected { agentR.connectButton.IsEnabled = false; agentR.sendSettingsConnect.Content = "Sending Data..."; agentR.loadSettingsConnect.IsEnabled = false; agentR.sendSettingsConnect.IsEnabled = false; agentR.DeviceRestore.IsEnabled = false; } public void deviceDisconnect(agentRadio agentR) //Adjusts display for when device is diconnected { agentR.portsOpen.IsEnabled = true; agentR.connectButton.IsEnabled = true; agentR.connectButton.Content = "Connect"; agentR.loadSettingsConnect.Content = "Load Settings"; agentR.sendSettingsConnect.Content = "Send Settings"; agentR.connectProgress.Value = 0; agentR.connectProgress.IsIndeterminate = false; agentR.loadSettingsConnect.IsEnabled = false; agentR.sendSettingsConnect.IsEnabled = false; agentR.DeviceRestore.IsEnabled = false; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload