|
-
Dec 11th, 2015, 12:02 PM
#1
Thread Starter
Hyperactive Member
[RESOLVED] Type of argument for .Invoke()
Hi folks
The MDSN page for the Control.Invoke method specifies:
Control.Invoke Method (Delegate)
Now I was given in my admittedly limited knowledge to understand that a delegate is just a variable that holds a reference to a function or sub and using a lamda in place ends up passing the same thing when used as a parameter; a reference to a function. (I think of this as similar to passing function pointers in C and a lambda parameter just passes a pointer for a function that's written as an argument)
This could be where the following confusion stems from I guess but here goes:
The argument is asked for as a delegate. Using 'SomeControl.Invoke(Sub() somesub(someargs))' works fine. seems to me that's because the argument is a lambda that is a Sub that calls some other sub.
Yet trying trying to use a Function lambda or a multi-line lambda does not work because (and here's the screen head-butting bit) "the expression does not produce a value"
...
But a lamda produces a value surely, the reference to the anonymous function?
And if not then how did the original single line Sub lambda work? If lambdas don't fulfil this requirement then how can any form of them work at all? Seems like it is supposed to take delegates but only works for particular types of them or when they're declared in particular ways??
Anyway what I'd like to end up with is being able to go:
vb Code:
SomeControl.Invoke(Sub() Foo() If (Something) then Bar() End If End Sub)
Instead of
vb Code:
Private Sub StupidHelperSub() Bar() If (something) Then Foo() End If End sub ... SomeControl.Invoke(Sub() StupidHelperSub())
Last edited by wolf99; Dec 11th, 2015 at 12:06 PM.
Thanks 
-
Dec 11th, 2015, 12:21 PM
#2
Thread Starter
Hyperactive Member
Re: Type of argument for .Invoke()
Furthermore, and separately: if the argument should be a delegate
How come neither of the following work?
vb Code:
somecontrol.Invoke(Foo()) SomeControl.Invoke(AddressOf Foo())
Thanks 
-
Dec 11th, 2015, 12:27 PM
#3
Thread Starter
Hyperactive Member
Re: Type of argument for .Invoke()
So I went back to the example on the Control.Invoke() MSDN page and used the exact syntax there (give or take some names!):
vb Code:
Delegate Sub StupidHelperDelegate() Sub StupidHelpersub() Foo() If (SomeCondition) Then Bar() End If End Sub ... Dim LordHelpUsAtThisLevelOfUselessSyntax As StupidHelperDelegate = New StupidHelperDelegate(AddressOf StupidHelperSub) SomeControl.Invoke(LordHelpUsAtThisLevelOfUselessSyntax)
This works. but as you might be able to tell, my opinion on having a type and a variable of that type to hold a reference to an address to 4 lines of code just to run those 4 lines of code in a language that has lambdas is the height of stupidity.
Surely there must be a more succinct method?
Thanks 
-
Dec 11th, 2015, 02:14 PM
#4
Re: Type of argument for .Invoke()
Code:
Delegate Sub StupidEnquirerDelegate()
Sub StupidEnquirersub()
If StupidEnquirerControl.InvokeRequired Then
'if the control needs invoking on the thread, the delegate recalls this method
StupidEnquirerControl.Invoke(New StupidEnquirerDelegate(AddressOf StupidEnquirersub))
Else
'if invoking has completed or is not necessary, this runs
StupidCodeName() 'such as Foo or Bar
End If
End Sub
Last edited by .paul.; Dec 11th, 2015 at 02:17 PM.
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Dec 11th, 2015, 03:25 PM
#5
Re: Type of argument for .Invoke()
Oooh. I don't know the answer to this, offhand. Which naturally means it sounds really fun to find the answer. Let's start with #2, which I CAN answer.
First sample:
Code:
someControl.Invoke(Foo())
The reason this is an error is because tacking a parameter list onto Foo means you're telling VB that you want to execute the method, and use the value it returns as the Delegate parameter to Invoke. That's also the reason this doesn't work:
Code:
someControl.Invoke(AddressOf Foo())
That's saying something similar, but we have to understand what AddressOf does: behind the scenes, it creates a Delegate for the method you give it, and returns that Delegate. So this line says, "Execute Foo(), then convert the Delegate it returns to a Delegate for Invoke()." But Foo() doesn't return a Delegate, so it fails. The appropriate syntax is:
Code:
someControl.Invoke(AddressOf Foo)
Sometimes parenthesis are optional in VB .NET, and the language fills them in for you. In this case, and a couple of others, they're mandatory and leaving them out has significance. This is why it's a joke that people say "VB is easy to learn", this rule's more like Perl than anything else. You could actually write a Function Foo() that returns a Delegate and your above code would work, I'm just not sure /which/ of the two lines it'd be.
Your #3 description is the way we had to do it in the Bad Old Days of .NET 1. Somewhere around VS 2005, AddressOf got a little more useful, and then when lambdas came out in VS 2008 many of the use cases for defining your own Delegate types went away. It's a syntax that always works, but I agree it's a bit much. (We also had to do this for all event handlers if we made our own events back then!)
So let's go back to #1. I was surprised this causes an error, so I had to test it myself. When I tried this code, it worked with no error:
Code:
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Button1.Invoke(Sub()
Foo()
If (True) Then
Bar()
End If
End Sub)
End Sub
But I don't think you're crazy. I've seen this error before when dealing with things that take various Delegates, and I think it's more common when something's taking Action() or Func(Of T), those have different conversion rules than Delegate.
If you have some code that's creating the error, I'm sure I could tell you what's going on if you post exactly that code.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
-
Dec 11th, 2015, 04:01 PM
#6
Re: Type of argument for .Invoke()
Would it be useful to know which version of VB.Net the OP is using, or anything 2010 and after should behave the same so doesn't matter?
-
Dec 11th, 2015, 04:07 PM
#7
Re: Type of argument for .Invoke()
True, I tested my code in VS 2010, but versions earlier than that might behave differently. I think VS 2005 didn't support lambdas?
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
-
Dec 14th, 2015, 06:10 AM
#8
Thread Starter
Hyperactive Member
Re: Type of argument for .Invoke()
Hi Folks,
Thanks for the discussion! I am using VS 2010.
So basically my use of invoke is down to the events fired off by a FileSystemWatcher being on a separate thread. When these events happen I want to read the files in the watched directory and update related items listed in a ComboBox. If one of the files is already open then the serialised object should also be updated, and any other controls bound to it.
After reading Sitten Spynne's post I tried the lambda sub again to find that it builds without issue, though I could swear this is exactly what I did first time around! Chalk it up to Friday frustrations maybe 
vb Code:
Private Sub FileWatcher_Changed(sender As System.Object, e As System.IO.FileSystemEventArgs) Handles _ FileWatcher.Changed, FileWatcher.Created, FileWatcher.Deleted, FileWatcher.Renamed If ProductComboBox.InvokeRequired Then ProductComboBox.Invoke(Sub() ScanProfiles() If (WorkingProfile IsNot Nothing) Then UpdateBindings(WorkingProfile) End If End Sub) Else ScanProfiles() If (WorkingProfile IsNot Nothing) Then UpdateBindings(WorkingProfile) End If End If End Sub
Thanks 
-
Dec 14th, 2015, 08:17 AM
#9
Re: Type of argument for .Invoke()
 Originally Posted by Sitten Spynne
True, I tested my code in VS 2010, but versions earlier than that might behave differently. I think VS 2005 didn't support lambdas?
It didn't.
If I remember right the progression was something like this:
VB2008 - Lambdas introduced, but only as functions, and only single-lined
VB2010 - Multi-line lambdas introduced, sub support also added
-tg
-
Dec 14th, 2015, 08:41 AM
#10
Re: [RESOLVED] Type of argument for .Invoke()
To make you feel better: sometimes Intellisense/whatever does the syntax checking gets confused, and a good reboot makes things right again. It's rare, but given the amount of time we spend at these tools, "rare" has to be /very/ rare for us to not see it.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|