私はデバイスとインターフェイスしており、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;
}