更新:
我正在使用'FileSystemWatcher'对象来监视文件,当它的OnChanged事件触发时,我将它用作更新我的DataGridView的提示。但是,在这样做时,我收到以下错误:“跨线程操作无效:控制'dgvSession'从其创建的线程以外的线程访问”。现在,在对该错误进行进一步研究后,很明显应该使用一个对象的Completed事件,并强调它应该是一个操作完成后触发的事件。 FileSystemWatcher只有一个OnChanged事件并且用它来更新数据网格视图不起作用 - 所以我跟着this link给了我toadflakz并实现了一个静态类来使用扩展方法来线程安全设置我的datagridview的数据源。这是静态类:
public static class CThreadSafe
{
private delegate void SetPropertyThreadSafeDelegate<TResult>(Control @this, Expression<Func<TResult>> property, TResult value);
public static void SetPropertyThreadSafe<TResult>(this Control @this, Expression<Func<TResult>> property, TResult value)
{
var propertyInfo = (property.Body as MemberExpression).Member as PropertyInfo;
if (propertyInfo == null ||
!@this.GetType().IsSubclassOf(propertyInfo.ReflectedType) ||
@this.GetType().GetProperty(propertyInfo.Name, propertyInfo.PropertyType) == null)
{
throw new ArgumentException("The lambda expression 'property' must reference a valid property on this Control.");
}
if (@this.InvokeRequired)
{
@this.Invoke(new SetPropertyThreadSafeDelegate<TResult>(SetPropertyThreadSafe), new object[] { @this, property, value });
}
else
{
@this.GetType().InvokeMember(propertyInfo.Name, BindingFlags.SetProperty, null, @this, new object[] { value });
}
}
}
但是,在使用此扩展方法设置属性时:
DataTable tblSession = new DataTable();
string sql = "SELECT * FROM crosssession ORDER BY MemberID";
MySqlDataAdapter daSession = new MySqlDataAdapter(sql, cnSession);
daSession.Fill(tblSession);
dgvSesssion.SetPropertyThreadSafe(() => dgvSesssion.DataSource, tblSession);
我陷入静态类的ArgumentException:“lambda表达式'property'必须引用此Control上的有效属性”。看起来我正在采取的行动不会在扩展方法的第一个IF语句中检出。
答案 0 :(得分:2)
确保您从正确的主题更新UI控件。 FileSystemWatcher
将在不是UI线程的线程上引发事件。
通常,这意味着您需要在UI托管类上创建一个界面,以检查在更新DataGridView
之前是否可以访问Control
。
可以在此处找到执行检查和调用所需的代码:How to update the GUI from another thread in C#?