Click here to Skip to main content
14,268,557 members
Rate this:
Please Sign up or sign in to vote.
See more:
I am trying to make a custom parallel for each statement to incorporate into a dll file.

I am having a hard time creating an object that displays as an delegate. I need the name to pass into the address of portion of the parallel for each statement.
I am trying to pass the name of the delegate as a string through the sub. The issue is I can not figure how to make the result variable useable in the address of.

Public Sub parallelforeach(startofiteration As Long, endofiteration As Long, subfunctionname As String)
       Dim result As [delegate]

       result = CallByName(Me, subfunctionname, CallType.Get, Nothing)
       ' CallByName()
       Dim numbers() = Enumerable.Range(startofiteration, endofiteration).ToArray
       ' CallByName(yourClassOrObjectName, "NameExample1", CallType.Set, oReader.ReadString)
       ' System.Threading.Tasks.Parallel.ForEach(numbers, processorcount, AddressOf process)
   End Sub

I am getting this error,
System.MissingMemberException: 'Public member 'process' on type 'Form1' not found.'

I was trying to find information on delegates and address of. Not much out there on the type of thing I am trying to accomplish.

What I have tried:

I have tried changing the delegate to an object. I have also tried to change the type.get to type.method see if that would help.
Updated 8-Aug-19 7:10am
Rate this:
Please Sign up or sign in to vote.

Solution 2

You need to create an Action(Of Integer) delegate given the name of a method on the current class:
Public Sub ParallelForEach(ByVal startOfIteration As Integer, ByVal endOfIteration As Integer, ByVal subFunctionName As String)
    Const flags As BindingFlags = BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Static Or BindingFlags.Instance
    ' Find the method with the specified name which accepts a single Integer parameter:
    Dim method As MethodInfo = Me.GetType().GetMethod(subFunctionName, flags, Nothing, New Type() { GetType(Integer) }, Nothing)
    If method Is Nothing Then
        Throw New ArgumentException(String.Format("Method '{0}' was not found.", subFunctionName), "subFunctionName")
    End If

    ' Create a delegate of the correct type pointing to the method:
    Dim del As System.Delegate
    If method.IsStatic Then
        del = System.Delegate.CreateDelegate(GetType(Action(Of Integer)), method)
        del = System.Delegate.CreateDelegate(GetType(Action(Of Integer)), Me, method)
    End If
    ' Cast the delegate to the correct type:
    Dim action As Action(Of Integer) = DirectCast(del, Action(Of Integer))
    ' NB: Second parameter to Range is the number of items to return, not the last number to return:
    Dim numbers As IEnumerable(Of Integer) = Enumerable.Range(startOfIteration, 1 + endOfIteration - startOfIteration)
    System.Threading.Tasks.Parallel.ForEach(numbers, processorCount, action)
End Sub
NB: The parameters to Enumerable.Range are Integer (32-bit), not Long (64-bit).

Also, the second parameter is the number of items to return, not the last number to return. Your parameter names suggest you're passing in the last number to return, so you have to adjust for that.

Since you're iterating over a fixed set of numbers, it would probably be better to use Parallel.For[^] instead of Parallel.ForEach.
Member 11856456 9-Aug-19 16:30pm
Richard, I am going to give this a whirl. Can you please explain what you mean by number of items to return. Can you give an example. and I think you are right I should switch to a parallel.for statement instead, is the set up of the example you have given the same?
Richard Deeming 12-Aug-19 14:12pm
The second parameter to Enumerable.Range[^] is count. The iterator will produce that many numbers - for example, if you call Enumerable.Range(10, 2), the returned iterator will produce { 10, 11 }.

Your parameter name - endOfIteration - makes me think that you want to pass the last number to return. For example, if you passed (startOfIteration := 10, endOfIteration := 11), you'd want { 10, 11 }, not { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }.
Richard Deeming 12-Aug-19 14:14pm
The basic version of Parallel.For also takes an Action(Of Integer), so the setup would be exactly the same. You'd just replace the final two lines with:
System.Threading.Tasks.Parallel.For(startOfIteration, 1 + endOfIteration - startOfIteration, action)
Rate this:
Please Sign up or sign in to vote.

Solution 1

Does your "Form1" have a "public" member called "process"?

How about a private one that you can make public?

Or, add one to Form1 and see what happens when it gets "called".

'? System.Threading.Tasks.Parallel.ForEach(numbers, processorcount, AddressOf process)
Member 11856456 4-Aug-19 18:57pm
Private Sub process(i As Long)
end sub

I changed the private to public and got a new message:
System.MissingMemberException: 'Overload resolution failed because no accessible 'process' accepts this number of arguments.'

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100