I'm going to need help with this one. Been 2 days now without figuring out the root case. In my application I add a set number of rows to a DataTable and display it through a DataGrid.
A timer is set to do some work on a interval (currently set to 10 seconds):
Adding the list of the computers to the DataTable and displaying them into DataGrid works fine. The problem occurs after I hit the Start button which triggers the timer. The amount of time it takes before the error occurs depends on how many rows are added to the DataTable.
Sorry for all the info posted below here. The frustration has kicked in for me. Hopefully someone can spot the obvious and help me get passed this problem. I have commented out some of the code to narrow the where the problem is located.
For testing purposes the intital DataTable is created and DataGrid is populated with an empty table when I click the Test button.
void FillDataGrid()
{
try
{
ds.ReadXml(@"C:\Temp\ToastData.ds");
gridToastItems.ItemsSource = ds.Tables[0].DefaultView;
}
catch (Exception ioException)
{
dt.Clear();
DataColumn column;
//ID Column
column = new DataColumn();
column.DataType = System.Type.GetType("System.Int32");
column.ColumnName = "id";
column.ReadOnly = true;
column.Unique = true;
column.AutoIncrement = true;
dt.Columns.Add(column);
//// Make the ID column the primary key column.
//DataColumn[] PrimaryKeyColumns = new DataColumn[1];
//PrimaryKeyColumns[0] = dt.Columns["id"];
//dt.PrimaryKey = PrimaryKeyColumns;
// Hostname column
column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "hostname";
column.Caption = "Hostname";
column.ReadOnly = false;
column.Unique = false;
column.AutoIncrement = false;
dt.Columns.Add(column);
// Online column
column = new DataColumn();
column.DataType = System.Type.GetType("System.Boolean");
column.ColumnName = "online";
column.Caption = "Online";
column.ReadOnly = false;
column.Unique = false;
column.AutoIncrement = false;
dt.Columns.Add(column);
// OS Version column
column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "osversion";
column.Caption = "OS Version";
column.ReadOnly = false;
column.Unique = false;
column.AutoIncrement = false;
dt.Columns.Add(column);
// Lockscreen status column
column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "lockscreen";
column.Caption = "Lockscreen Status";
column.ReadOnly = false;
column.Unique = false;
column.AutoIncrement = false;
dt.Columns.Add(column);
// Toast type column
column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "toasttype";
column.Caption = "Toast Type";
column.ReadOnly = false;
column.Unique = false;
column.AutoIncrement = false;
dt.Columns.Add(column);
// Schedule column
column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "schedule";
column.Caption = "Schedule";
column.ReadOnly = false;
column.Unique = false;
column.AutoIncrement = false;
dt.Columns.Add(column);
// Result column
column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "status";
column.Caption = "Status";
column.ReadOnly = false;
column.Unique = false;
column.AutoIncrement = false;
dt.Columns.Add(column);
ds.Tables.Add(dt);
gridToastItems.ItemsSource = dt.DefaultView;
//DataColumn hostname = new DataColumn("Hostname", typeof(string));
//DataColumn online = new DataColumn("Online", typeof(bool));
//DataColumn osversion = new DataColumn("OS Version", typeof(string));
//DataColumn lockscreen = new DataColumn("Lockscreen Status", typeof(string));
//DataColumn toastname = new DataColumn("Toast Type", typeof(string));
//DataColumn schedule = new DataColumn("Schedule", typeof(string));
//DataColumn result = new DataColumn("Result", typeof(string));
//dt.Columns.Add(hostname);
//dt.Columns.Add(online);
//dt.Columns.Add(osversion);
//dt.Columns.Add(lockscreen);
//dt.Columns.Add(toastname);
//dt.Columns.Add(schedule);
//dt.Columns.Add(result);
//dt.AcceptChanges();
//gridToastItems.ItemsSource = dt.DefaultView;
//ds.Tables.Add(dt);
//ds.AcceptChanges();
}
}
The computers are added to the DataTable from a second form:
private void AddToastEntries()
{
bool exceptionCaught = false;
try
{
int lineCount = txtComputerNames.LineCount; //iterator for number of computernames in the textbox
if (lineCount > 1)
{
for (int i = 0; i < lineCount; i++)
{
string currentLine = txtComputerNames.GetLineText(i).ReplaceLineEndings("");
//Adding a new toast entry for each computername listed in the textbox
if (currentLine != "")
{
DataRow firstRow = MainWindow.ds.Tables[0].NewRow();
firstRow["hostname"] = currentLine;
firstRow["online"] = false;
firstRow["osversion"] = "";
firstRow["lockscreen"] = "";
firstRow["toasttype"] = "Windows Update";
firstRow["schedule"] = SelectedDateTime();
firstRow["status"] = "Pending";
MainWindow.ds.Tables[0].Rows.Add(firstRow);
//MainWindow.ds.Tables[0].AcceptChanges();
//MainWindow.ds.AcceptChanges();
}
}
}
}catch(Exception newToastEntriesException)
{
exceptionCaught = true;
}
if(exceptionCaught)
{
MessageBox.Show("Failed to add current selection to schedule\n Check that a valid date and time is selected", "Error" ,MessageBoxButton.OK ,MessageBoxImage.Asterisk);
}
}
Here's the code running from the window above when I click the Start button
private async void timer_Tick(object sender, EventArgs e)
{
await Task.Run(() => ProcessToastMessages());
}
private void ProcessToastMessages()
{
WindowsToasts.WindowsToast windowsUpdateToast = new WindowsToast(); //creating a new instance of a toast message
int rowCount = 0;
rowCount = ds.Tables[0].Rows.Count;
for (int i = 0; i <= (rowCount - 1); i++)
{
DateTime scheduledTime = DateTime.Now;
//try
//{
DateTime.TryParse(ds.Tables[0].Rows[i]["schedule"].ToString(), out scheduledTime); //Converting the string value of date in the to a type of DateTime
string currentStatus = ds.Tables[0].Rows[i]["status"].ToString();
if ((scheduledTime.Ticks < DateTime.Now.Ticks) && currentStatus == "Pending")
{
string computerName = ds.Tables[0].Rows[i]["hostname"].ToString(); // Gets the computername in currentrow
bool isOnline = ComputerFuncs.ComputerOnline(computerName); // Checking if computer is online (Ping)
switch (isOnline)
{
case true:
//try
//{
ds.Tables[0].Rows[i].SetField("online", true);
//windowsUpdateToast.Send_WindwsUpdateToast(computerName); //Sending toast notification if computer is online
ds.Tables[0].Rows[i].SetField("status", "Sent");
//ds.Tables[0].Rows[i]["status"] = "Sent";
// break;
////}
////catch (Exception psException)
////{
// ds.Tables[0].Rows[i]["online"] = false;
//ds.Tables[0].Rows[i].SetField("online", false);
//ds.Tables[0].Rows[i].SetField("status", "Failed");
// ds.Tables[0].Rows[i]["status"] = "Failed";
// //break;
//}
break;
case false:
ds.Tables[0].Rows[i].SetField("online", false);
break;
}
}
//}
//catch (Exception dateTimeException)
//{
//}
}
}
private void btn_StartStop_Click(object sender, RoutedEventArgs e)
{
// ds.WriteXml((@"C:\temp\ToastData.ds"), XmlWriteMode.WriteSchema);
string btnCurrentText = btn_StartStop.Content.ToString();
if(btnCurrentText == "Start")
{
gridToastItems.IsReadOnly = true;
btn_Schedule.IsEnabled = false;
StartToastMonitoring(true);
}
else if(btnCurrentText == "Stop")
{
StartToastMonitoring(false);
gridToastItems.IsReadOnly = false;
btn_Schedule.IsEnabled = true;
}
}
Error I'm getting is shown below. The iterator seems to be within bounds of the number of rows as far as I can tell.
I have figured what is causing problems. The process of pinging the computers is taking an extreme amount of time if the ping function is unable to get a ping result and a ping exception is thrown.
The interval of the timer had to be increased to allow all the processing to complete. I will figure out another way and try to ping the computers in parallel.