我正在与设备连接,并使用c#从设备发送和接收大约2000个字节。我发现如果单击我的连接按钮并让它运行,该过程将在80%的时间内完成,并且20%的时间会发生读取超时。这本身就是一个问题。
此外,如果我在读取数据时根本移动窗口,则会发生读取超时。我认为这可能是一个优先问题,所以我尝试搞乱后台工作程序和接口线程的优先级,但没有运气。
之前有没有人发生过这种情况?建议表示赞赏。以下是相关的代码,如果您认为需要更多代码,请告诉我,我也会发布。提前谢谢。
从以下地方调用函数:
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 & 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);
}
}
所谓的函数:
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 < 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 < 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 < 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 < 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 < 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 < 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 > 0 && iteration < 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 > 384 && iteration < 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 > 1284 && iteration < 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 > 1344 && iteration < 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 > 1944 && iteration < 1973) //read holidays
{
Create.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);
Create.messages[i, j] = value;
}
if (iteration > 2167 && iteration < 2196) //read message info
{
Create.recordings[iteration - 2168] = value;
}
if (iteration > 2195 && iteration < 2246) //read sysval
{
Create.sysval[iteration - 2196] = value;
}
if (iteration == 2246 && 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 > 0 && iteration < 51) //sysval
{
byte[] toWrite = new byte[1];
toWrite[0] = Create.sysval[iteration - 1];
agentSerial.Write(toWrite, 0, 1);
value = (byte)agentSerial.ReadByte();
}
if (iteration > 50 && iteration < 79) //holiday
{
byte[] toWrite = new byte[1];
toWrite[0] = Create.holidays[iteration - 51];
agentSerial.Write(toWrite, 0, 1);
value = (byte)agentSerial.ReadByte();
}
if (iteration > 78 && iteration < 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 > 462 && iteration < 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 && ((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
}
}
表格类:
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;
}
答案 0 :(得分:0)
不要在DoWork处理程序中使用ProgressBar对象。 ProgressChanged处理程序(readWorker_ProgressChanged)应该获得报告进度本身所需的一切。
另外,为什么要调度IsIndeterminate的设置?
另外。将始终在UI线程上调用ProgressChanged处理程序(除非您自己直接调用它,否则无需在readWorker_ProgressChanged中调度任何内容。
我还会避免手动调度回设备,例如deviceReading和deviceDisconnect。这就是进展事件的目的。
我之所以避免这种情况,是因为您要回发UI线程进行这些操作 - 这意味着您的后台线程被阻止,直到UI可以调用这些操作。如果UI正忙于重新绘制屏幕或处理菜单选项,则无法处理此操作。这会暂停您的后台工作,直到UI线程可以处理它,从而超时串行通信。