Passing a method as an argument for another method:
Public Sub NewThread(Method As Action)
Me.TaskThread = New Thread(New ThreadStart(Method))
End Sub
Results for error:
Error BC32008: "Delegate 'ThreadStart' requires an 'AddressOf' expression or lambda expression as the only argument to its constructor."
And
Public Sub NewThread(Method As Action)
Me.TaskThread = New Thread(New ThreadStart(AddressOf Method))
End Sub
Results for error:
Error BC30577: "'AddressOf' operand must be the name of a method (without parentheses)."
What went wrong and how to fix it?
The constructor of Thread expects a delegate. Traditionally, if you have a method, say, MyMethod:
Private Sub MyMethod()
' Do stuff.
End Sub
You'd call the constructor as follows:
Me.TaskThread = New Thread(AddressOf MyMethod)
Notice that AddressOf is to be followed by the name of the method (without parentheses). But since you have the method as a delegate parameter (of type Action), you need to pass as a lambda expression like this:
Me.TaskThread = New Thread(Sub() Method())
Related
I have a global method (in a module) that multiple forms are calling. I can't figure out how to pass/identify the calling form so that it's controls are recognised when referenced in the method:
Public Sub SomeFunction(callingForm As Form)
callingForm.ErrorProvider.SetError(TextBox1, "Faux pas!")
End Sub
Public Sub SomeOtherFunction(callingForm As Form)
SomeFunction(Me)
End Sub
I the above example, I've attempted passing the form as a parameter but I'm being told:
ErrorProvider is not a member of System.Windows.Forms.Form.
This is pretty common, to want to treat all your forms the same, yet different. You will want to create another class that each form can implement. This allows you to do something specific... generically.
Create a class similar to this, call it and the function whatever you want:
Public Interface IErrorForm
Sub MyValidate
End Interface
Implement it in your forms:
Public Class Form1
Implements IErrorForm
Public Sub MyValidate() Implements IErrorForm.MyValidate
'...Your code here
'TextBox1.Text = "Faux pas!"
End Sub
Now, wherever you want to call the function, you could do something like this:
Public Sub SomeFunction(callingForm As Form)
If GetType(IErrorForm).IsAssignableFrom(xFrm.GetType) Then
CType(xFrm, IErrorForm).MyValidate()
End If
End Sub
Another approach with returning value from Validate function
As you mentioned in the comments
...one of the key purposes of my method is to avoid having to set the
errors outside of the method, to reduce duplicitous code
As I understand you want Validate function check, given control as parameter, for errors and show error message through ErrorProvider.
My suggestion will be shared Validate function return string value, which contains error message generated after validating control
If no error then function return Nothing or String.Empty
Public Function Validate(ctrl As Object, formats As String) As String
Dim errorMessage As String = Nothing 'or String.Empty
' Your validating code here
' If no error errorMessage = Nothing
Return errorMessage
End Function
Then in the form (possible in the Validated event handler)
'....
Me.MyErrorprovider.SetError(Me.MyTextBox,
MyGlobalFunctions.Validate(Me.MyTextBox, "formats"))
I'm used to programming in C# so I have no idea how to approach delegates and passing methods in VB
The error that I am getting is: Argument not specified for parameter 'message' of 'Public Sub ReceiveMessage(message As String)'
Here is the constructor of the class that I am trying to pass to:
Delegate Sub ReceiveDelegate(message As String)
Public ReceiveMethod As ReceiveDelegate
Sub New(ByRef receive As ReceiveDelegate)
ReceiveMethod = receive
End Sub
This is the method that I am trying to pass to that constructor:
Public Sub ReceiveMessage(message As String)
MessageBox.Show(message)
End Sub
I'm using it as such:
Dim newClass As New Class(ReceiveMessage)
The purpose of this, is that once the class receives data from a network device, it can call the corresponding method on the Form asynchronously.
You need to create the delegate object and use the AddressOf operator, like this:
Dim newClass As New Class(New ReceiveDelegate(ReceiveMessage))
However, if you don't explicitly create the delegate object, VB.NET will automatically determine the right type, based on the signature, and create it for you, so you can just do it like this:
Dim newClass As New Class(AddressOf ReceiveMessage)
The latter is obviously less typing, but the former is more explicit. So, take your pick. Both ways are perfectly acceptable and common.
ok I do have class like this.
Namespace mySpace
Public Class ClassA
Private Function MethodA(prm AS Boolean) As Boolean
Return False
End Function
Private Function MethodB() As Boolean
Return False
End Function
End Class
Public Class ClassB
Private Function MethodC() As Boolean
Return True
End Function
Private Function InvokeA() As Boolean
Dim methodObj As MethodInfo
'null pointer except below here
methodObj = Type.GetType("mySpace.ClassA").GetMethod("MethodA")
Dim params As Boolean() = {False}
Return CBool(methodObj.Invoke(New ClassA(), params))
End Function
End Class
End Namespace
What I am trying here is to invoke a method from a different class with parameters using its method. But this returns a null pointer exception. Why? Where I went wrong?
You are doing various things wrong. The following code should work without any problem:
Dim objA As ClassA = New ClassA()
methodObj = objA.GetType().GetMethod("MethodA", BindingFlags.Instance Or BindingFlags.NonPublic)
Dim params As Object() = {False}
methodObj.Invoke(objA, params)
You have various errors which shouldn't allow your code to run at all, namely:
You are retrieving a private method without the adequate
BindingFlags.
You are not passing the arguments as Object type.
Additionally, you are not using GetMethod with an instantiated object of ClassA (e.g., objA above) and instance.GetType(); I am not 100% sure that you need to do that (perhaps you can accomplish it as you intend), but performing this step is a pretty quick process and would allow the code above to work without any problem.
I am trying to create a new thread using an anonymous function but I keep getting errors. Here is my code:
New Thread(Function()
'Do something here
End Function).Start
Here are the errors I get:
New:
Syntax Error
End Function:
'End Function' must be preceded by a matching 'Function'.
There's two ways to do this;
With the AddressOf operator to an existing method
Sub MyBackgroundThread()
Console.WriteLine("Hullo")
End Sub
And then create and start the thread with;
Dim thread As New Thread(AddressOf MyBackgroundThread)
thread.Start()
Or as a lambda function.
Dim thread as New Thread(
Sub()
Console.WriteLine("Hullo")
End Sub
)
thread.Start()
It is called a lambda expression in VB. The syntax is all wrong, you need to actually declare a variable of type Thread to use the New operator. And the lambda you create must be a valid substitute for the argument you pass to the Thread class constructor. None of which take a delegate that return a value so you must use Sub, not Function. A random example:
Imports System.Threading
Module Module1
Sub Main()
Dim t As New Thread(Sub()
Console.WriteLine("hello thread")
End Sub)
t.Start()
t.Join()
Console.ReadLine()
End Sub
End Module
What is called has to be a functinon not a sub.
Single line(has to return value):
Dim worker As New Thread(New ThreadStart(Function() 42))
Multiline:
Dim worker As New Thread(New ThreadStart(Function()
' Do something here
End Function))
Source: Threading, Closures, and Lambda Expressions in VB.Net
How can I put AddressOf, from another class?
I get this error 'AddressOf' operand must be the name of a method (without parentheses). "
Is there an Eval () function in VB.NET? Or how does one do this?
Public Shared Property e As UserControl
Public Shared Sub SetButton(ByVal button As String, ByVal Objekt As [Delegate])
Dim errorbuttom1 As Button = e.FindName("errorButton1")
AddHandler errorbuttom1.Click, AddressOf Objekt
End Sub
You have to have an instance of Objekt, and the method that's the delegate must be public and match the signature of the delegate. Or, the method must be public static.
I believe that would work...