【问题标题】:Cross-thread operation not valid - DataGridView Updating Data Source跨线程操作无效 - DataGridView 更新数据源
【发布时间】:2014-11-21 16:55:49
【问题描述】:

更新:

我正在使用“FileSystemWatcher”对象来监视文件,当它触发 OnChanged 事件时,我使用它作为更新我的 DataGridView 的提示。然而,这样做我得到了以下错误:“跨线程操作无效:控制'dgvSession'从创建它的线程以外的线程访问”。现在在对该错误进行进一步研究后,很明显应该使用对象的 Completed 事件,并强调它应该是在操作完成后触发的事件。 FileSystemWatcher 只有一个 OnChanged 事件并且用它更新数据网格视图不起作用 - 所以我遵循this link toadflakz 给了我并实现了一个静态类来使用扩展方法来线程安全地设置我的数据源数据网格视图。这是静态类:

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' 必须引用此控件上的有效属性”。看来我正在采取的行动并没有在扩展方法中的第一个 IF 语句中签出。

【问题讨论】:

  • “这会解决我的问题”——我认为不会。问题在于您在哪个线程上,而不是文件是否已完成更新。

标签: c# multithreading datagridview


【解决方案1】:

确保从正确的线程更新 UI 控件。 FileSystemWatcher 将在不是 UI 线程的线程上引发事件。

通常这意味着您需要在 UI 托管类上创建一个接口,以检查您是否可以在更新 Control 之前访问 DataGridView

检查和调用所需的代码可以在这里找到:How to update the GUI from another thread in C#?

【讨论】:

  • 会试一试。谢谢
  • 我更新了我原来的帖子。
猜你喜欢
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多