我正在尝试更新后台工作程序中的Ultragridrow单元格,但是当调用超过1次时,这会抛出一个InvalidOperation异常。
这里有启动RunWorkerAsync的方法。
private void RefreshGridCacheStart()
{
try
{
if (this.uGridCache.Rows.Count == 0)
{
return;
}
if(!workerThread.IsBusy)
{
workerThread.DoWork += LookUpHostnames;
workerThread.ProgressChanged += UpdateCacheHostCell;
workerThread.RunWorkerCompleted += WorkerCompleted;
workerThread.WorkerReportsProgress = true;
workerThread.RunWorkerAsync();
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message + "\n" + ex.Source + "\n" + ex.ToString());
}
}
这是DoWork方法:
private void LookUpHostnames(object sender, DoWorkEventArgs e)
{
var rowValues = new object[2];
try
{
foreach (UltraGridRow row in uGridCache.Rows)//here is were I get an invalid operation exception
{
string cellValue = row.Cells["Host"].Text;
if (Globals.cNet.isValidIP(cellValue))
{
rowValues[0] = row;
rowValues[1] = cellValue;
workerThread.ReportProgress(0, rowValues);
string resolvedHostname = Globals.cIPLookup.LookupHostFromIP(cellValue);
rowValues[1] = resolvedHostname;
workerThread.ReportProgress(0, rowValues);
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message + "\n" + ex.Source + "\n" + ex.ToString());
}
}
这是报告进度方法:
private void UpdateCacheHostCell(object sender, ProgressChangedEventArgs e)
{
var rowValues = e.UserState as object[];
var row = (UltraGridRow) rowValues[0];
var sMesage = (string) rowValues[1];
row.Cells["Host"].Value = sMesage;
}
答案 0 :(得分:0)
您可以找到答案here不同的问题,但最终会遇到同样的问题。您正在更改foreach循环内的数据,这会使枚举器无效 我从阅读您的代码中看到了两种可能的解决方案
答案 1 :(得分:0)
听起来像是必须更改基础行集合,因此使您的可枚举无效。
如果使用.ToList()
将可枚举转换为列表(这将导致可枚举迭代并为您提供包含原始项目的新列表),您将能够迭代这个新的可枚举和更改在源中不会影响你。
foreach (UltraGridRow row in uGridCache.Rows.ToList())
{
....
workerThread.ReportProgress(0, rowValues);
}
您必须注意,如果其他内容正在更改网格上的行,您的ReportProgress可能会报告网格中不再存在的内容的进度,您可能需要检查ReportProgress处理程序是否报告进度在做任何事情之前,该项目仍然有效。
答案 2 :(得分:0)
DoWork上的MSDN文档说明如下: “您必须小心不要操纵DoWork事件处理程序中的任何用户界面对象。而是通过BackgroundWorker事件与用户界面进行通信。”。
您可以在此处查看DoWork方法的完整详细信息: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.dowork.aspx
从此事件访问UltraGridRows会导致您从另一个线程访问UltraGrid,并且Windows窗体控件不是线程安全的。
请注意,这不仅限于访问控件的属性。如果要在UltraGrid绑定的数据源中设置值,则会出现相同的问题,因为更改通知会在后台线程上发生,UI仍然会从后台线程进行操作。
请注意,在Windows窗体控件上只有少数成员实际上是线程安全的,这些内容在MSDN上的“线程安全控制”一节中进行了说明:http://msdn.microsoft.com/en-us/library/system.windows.forms.control.aspx
Windows窗体中的安全,简单多线程是Windows窗体中线程的一个很好的资源,即使它更老:
如何:对Windows窗体控件进行线程安全调用也是一个很好的资源 http://msdn.microsoft.com/en-us/library/ms171728.aspx