0

UPDATE :

I'm using a 'FileSystemWatcher' object to monitor a file and when it's OnChanged event fires, i use it as a cue to update my DataGridView. However in doing so i got the following error : "Cross-thread operation not valid: Control 'dgvSession' accessed from a thread other than the thread it was created on". Now upon further research on that error, it is clear that one should use an object's Completed event, with emphasis on the fact that it should be the event that fires AFTER an operation completes. The FileSystemWatcher only has a OnChanged Event and updating the Data Grid View with it does not work - So i followed this link that toadflakz gave me and implemented a static class to use the extension method to thread-safe set the datasource of my datagridview. Here is static class :

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 });
        }
    }
}

However, while seting the property with this extension method :

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);

I fall into the ArgumentException of the static class that reads : "The lambda expression 'property' must reference a valid property on this Control". It would seem that the action i'm taking doesn't check out at the first IF statement in the extension method.

Community
  • 1
  • 1
Marnus_Steyn
  • 313
  • 1
  • 4
  • 9
  • 2
    "This would solve my problem" - I don't think that it would. The problem is to do with which thread you're on, not whether the file has finished being updated. – Jon Skeet Nov 21 '14 at 16:58

1 Answers1

2

Make sure you're updating the UI control from the correct thread. FileSystemWatcher will be raising an event on a thread that is not the UI thread.

Typically this means you need to create an interface on your UI hosting class that checks whether you can access the DataGridView before updating the Control.

The code required to do the checking and invoking can be found here: How to update the GUI from another thread in C#?

Community
  • 1
  • 1
toadflakz
  • 7,764
  • 1
  • 27
  • 40