C# WPF 应用程序 - 在运行时修改数据表时出现问题 - System.ArgumentOutOfRangeException
C# WPF App - Problem with modifying datatable during runtime - System.ArgumentOutOfRangeException
我需要这方面的帮助。现在已经 2 天了,还没有弄清楚根本原因。
在我的应用程序中,我将一定数量的行添加到 DataTable 并通过 DataGrid 显示它。
定时器设置为按一定间隔(当前设置为 10 秒)做一些工作:
- 在 DataTable 上逐行迭代。
- 从“主机名”列获取主机名
- Ping 计算机
- 如果 pingresult == 成功继续操作并发送 Windows Toast 消息。
将计算机列表添加到 DataTable 并将它们显示到 DataGrid 中效果很好。
问题发生在我按下触发计时器的“开始”按钮后。发生错误所需的时间取决于向 DataTable 添加了多少行。
对于下面发布的所有信息,我们深表歉意。我开始感到沮丧。希望有人能发现明显的问题并帮助我解决这个问题。我已经注释掉了一些代码以缩小问题所在的范围。
出于测试目的,当我单击“测试”按钮时,创建了初始数据表并用空 table 填充了 DataGrid。
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();
}
}
从第二种形式将计算机添加到 DataTable:
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);
}
}
这是我单击“开始”按钮时来自上面 window 的代码 运行
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;
}
}
我遇到的错误如下所示。据我所知,迭代器似乎在行数范围内。
我已经知道是什么导致了问题。如果 ping 功能无法获得 ping 结果并引发 ping 异常,则 ping 计算机的过程会花费大量时间。
必须增加计时器的间隔才能完成所有处理。我会想出另一种方法并尝试并行 ping 计算机。
我需要这方面的帮助。现在已经 2 天了,还没有弄清楚根本原因。 在我的应用程序中,我将一定数量的行添加到 DataTable 并通过 DataGrid 显示它。
定时器设置为按一定间隔(当前设置为 10 秒)做一些工作:
- 在 DataTable 上逐行迭代。
- 从“主机名”列获取主机名
- Ping 计算机
- 如果 pingresult == 成功继续操作并发送 Windows Toast 消息。
将计算机列表添加到 DataTable 并将它们显示到 DataGrid 中效果很好。 问题发生在我按下触发计时器的“开始”按钮后。发生错误所需的时间取决于向 DataTable 添加了多少行。
对于下面发布的所有信息,我们深表歉意。我开始感到沮丧。希望有人能发现明显的问题并帮助我解决这个问题。我已经注释掉了一些代码以缩小问题所在的范围。
出于测试目的,当我单击“测试”按钮时,创建了初始数据表并用空 table 填充了 DataGrid。
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();
}
}
从第二种形式将计算机添加到 DataTable:
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);
}
}
这是我单击“开始”按钮时来自上面 window 的代码 运行
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;
}
}
我遇到的错误如下所示。据我所知,迭代器似乎在行数范围内。
我已经知道是什么导致了问题。如果 ping 功能无法获得 ping 结果并引发 ping 异常,则 ping 计算机的过程会花费大量时间。
必须增加计时器的间隔才能完成所有处理。我会想出另一种方法并尝试并行 ping 计算机。