Search code examples
vb.netdatagridviewinvoke

I don't understand what the syntax should be for this datagridview new action invoke command


I'm trying to generate a program to monitor a database file for changes and to return the last 10 entries in a datagridview list.

I've searched a mountain of Google references relating to Invoke and New Action and tried various iterations of code, but as I don't fully understand the Invoke New Action statement even after reading Microsoft documents and forum references, I can't make the syntax correct.

Private Sub UpdateDgvThread()
    RemoveHandler watcher.Changed, AddressOf OnChanged
    DataGridView1.Invoke(New Action(AddressOf UpdateDgv))
    AddHandler watcher.Changed, AddressOf OnChanged
End Sub

I get a 'Too few type arguments to 'System.Action(Of T)' error when running the program and the closest I've come is changing the error line to

DataGridView1.Invoke(New Action(Of ????)(AddressOf UpdateDgv))

which seems to be a corrected syntax(?) but I don't know what the ???? should be.


Solution

  • It looks like you are trying to pass the address of a method with arguments into the constructor of Action (the version with no generic type arguments).

    Instead, you should state the type(s) of the argument(s) to UpdateDgv by using the correct constructor

    New Action(Of T, ...)()
    

    Here are three possible versions of UpdateDgv, and their corresponding Invoke calls.

    Private Sub UpdateDgv0()
    End Sub
    
    Private Sub UpdateDgv1(arg1 As Object)
    End Sub
    
    Private Sub UpdateDgv2(arg1 As Object, arg2 As EventArgs)
    End Sub
    
    Private Sub UpdateDgvThread()
        DataGridView1.Invoke(New Action(AddressOf UpdateDgv0))
        DataGridView1.Invoke(New Action(Of Object)(AddressOf UpdateDgv1), New Object())
        DataGridView1.Invoke(New Action(Of Object, EventArgs)(AddressOf UpdateDgv2), New Object(), New EventArgs())
    End Sub
    

    Another option is to just use an anonymous method to wrap around the call to UpdateDgv, and you won't see the Action constructor at all. This works because Sub() satisfies Delegate, just like Action, but the function pointer AddressOf alone does not.

    DataGridView1.Invoke(Sub() UpdateDgv0())
    DataGridView1.Invoke(Sub() UpdateDgv1(New Object()))
    DataGridView1.Invoke(Sub() UpdateDgv2(New Object(), New EventArgs()))
    

    Since you're using .NET 3.0, you won't see the parameterless Action, which was introduced in 3.5. You could make your own Action delegate pretty simply. Adding this to your original code would also have solved the problem

    Private Delegate Sub Action()
    

    It is superior to the DataGridView1.Invoke(Sub() UpdateDgv()) approach because it involves one less call on the stack trace (though the compiler may optimize it away, I'm not sure).