Converting Delegates in C#for a Thread

N8800SS

New member
Joined
Oct 15, 2008
Messages
2
Programming Experience
Beginner
Hi All,

Sorry if this is the wrong place but first time here and I am still getting my bearings. I am currently working on a mobile appilication utilizing the Environmental System Research Institute's(ESRI) Mobile SDK. I need to start a thread with the below address of passing in a X,Y point from a mouse click. I have the code to do so in C# but cannot get it to work in vb.net. Let me know if you have any suggestions as simple code converters do not work...


C# code:

private void map1_MouseUp(object sender, ESRI.ArcGIS.Mobile.MapMouseEventArgs e)
{
if (startGP)
{
startGP = false;
Thread GPThread = new Thread(delegate() { CreateServiceAreaLayer(e.MapCoordinate.X, e.MapCoordinate.Y); });
GPThread.Start();
}
}



What I have tried:


Dim GPThread As New Thread(AddressOf (CreateServiceAreaLayer(e.MapCoordinate.X, e.MapCoordinate.Y)))
GPThread.Start()
 
More accurately define "cannot get it to work"

The syntax looks fine: Thread Class (System.Threading) says in VB this is how a thread is started

ps; why would you be writing a service, and using mouse events? services shouldnt respond or rely on mouse events, because it's not even certain that they run in a GUI context
 
more specifically the delegate in c# is a separate function within the thread... how would you accomplish this in VB? I basically need to the above code translated to VB.NET

Thanks!
 
That C# code is using an anonymous method. Anonymous methods don't exist in VB. That would explain why you can't convert the code. Lambda expressions incorporate some of the functionality of anonymous methods but lambda expressions exist specifically to support LINQ so they only provide the functionality that LINQ requires. Basically, there is no VB equivalent for that C# code. What you can do is convert the C# to use a conventional method and then convert that to VB code. So, this is your original C# code:
VB.NET:
private void map1_MouseUp(object sender, ESRI.ArcGIS.Mobile.MapMouseEventArgs e)
{
    if (startGP)
    {
        startGP = false;
        Thread GPThread = new Thread(delegate() { CreateServiceAreaLayer(e.MapCoordinate.X, e.MapCoordinate.Y); });
        GPThread.Start();
    }
}
This would be the equivalent using a conventional method instead of an anonymous method:
VB.NET:
private void map1_MouseUp(object sender, ESRI.ArcGIS.Mobile.MapMouseEventArgs e)
{
    if (startGP)
    {
        startGP = false;
        Thread GPThread = new Thread(MyConventionalMethod);
        GPThread.Start(new Point(e.MapCoordinate.X, e.MapCoordinate.Y));
    }
}

private void MyConventionalMethod(object mapCoordinate)
{
    Point pt = (Point)mapCoordinate;
    CreateServiceAreaLayer(pt.X, pt.Y);
}
Note that a named method, i.e. MyConventionalMethod, has replaced:
VB.NET:
delegate() { CreateServiceAreaLayer(e.MapCoordinate.X, e.MapCoordinate.Y); }
which is the anonymous method, in the Thread constructor. Also, notice that you must now actually pass data when you call Start because the data was previously part of the anonymous method. The VB equivalent of that code would be:
VB.NET:
Private Sub map1_MouseUp(ByVal sender As Object, ByVal e As ESRI.ArcGIS.Mobile.MapMouseEventArgs)
    If startGP Then
        startGP = False
        Dim GPThread As New Thread(AddressOf MyConventionalMethod)
        GPThread.Start(New Point(e.MapCoordinate.X, e.MapCoordinate.Y))
    End If
End Sub

Private Sub MyConventionalMethod(ByVal mapCoordinate As Object)
    Dim pt As Point = DirectCast(mapCoordinate, Point)
    CreateServiceAreaLayer(pt.X, pt.Y)
End Sub
Note that I have used a silly name like MyConventionalMethod to make sure it's obvious what method I'm using but in a real application I would probably overload the name CreateServiceAreaLayer.
 
How about :

dim GPThread as new Thread(ctype(function() CreateServiceAreaLayer(e.MapCoordinate.X, e.MapCoordinate.Y), ThreadStart))

GPThread.start()

NOTE your method (CreateServiceAreaLayer) must be a function, not a sub, otherwise you will get a compile-time error.

This seems to work for me in .Net 3.5.
 
Last edited:
hey can anyone apprise me

VB.NET:
'note the small g in gPThread; official naming convention
Dim gPThread As New Thread(AddressOf CreateServiceAreaLayer)
why AddressOf uses.. i dn't this meaning.. plz...i have seen this many place bt can't figure out

n other ques:
VB.NET:
dim GPThread as new Thread(ctype(function() CreateServiceAreaLayer(e.MapCoordinate.X, e.MapCoordinate.Y), ThreadStart))
is this really valid VB code.. bcoz i couldn't understand it clrly..

i have no idea in thread bt why n also that line of is seem very complex too me.. is there any can. help me too understand this
 
hey can anyone apprise me

VB.NET:
'note the small g in gPThread; official naming convention
Dim gPThread As New Thread(AddressOf CreateServiceAreaLayer)
why AddressOf uses.. i dn't this meaning.. plz...i have seen this many place bt can't figure out
Did you read the MSDN documentation for the AddressOf operator? That should have been your first stop.

A delegate is an object that contains a reference to a method. That reference is acquired using the AddressOf operator. Under the hood it's a function pointer, so the delegate contains the memory address of a function.
n other ques:
VB.NET:
dim GPThread as new Thread(ctype(function() CreateServiceAreaLayer(e.MapCoordinate.X, e.MapCoordinate.Y), ThreadStart))
is this really valid VB code.. bcoz i couldn't understand it clrly..

i have no idea in thread bt why n also that line of is seem very complex too me.. is there any can. help me too understand this
Yes, that certainly is valid VB code but, I have to admit, I'm surprised that it works. The Function key word is new in VB 2008 and is another way to create a reference to a method. This time though the method is a lambda expression, which is much like a C# anonymous method. You define the function inline rather than conventionally and it cannot be referred to anywhere else. What surprises me is that you can cast a lambda expression, which must by definition return a value, as a ThreadStart delegate, which has no return value.

Finally, can you please not use abbreviations like "bt" and "n" in future? There's no need for speed or brevity when posting to forums as there is in SMS or IM so those annoying abbreviations are not needed. Clarity is what you should strive for when posting to forums, not brevity.
 
What surprises me is that you can cast a lambda expression, which must by definition return a value, as a ThreadStart delegate, which has no return value.

I'm not as surprised by this. The given lambda is a statement lambda, not an expression lambda, ergo it has no return type. VB doesnt seem to make any kind of split between the two, i.e. it doesnt require the programmer to use Sub() to define a statement lambda and Function() to define an expression lambda.

Because this lambda has no return value, it's effectively a sub and I presume that the compiler detects this and creates the underlying code for a sub. Therefore it can be cast as a ThreadStart.

What surprises me is that MSDN defines in VB, a lambda expression as "A lambda expression is a function without a name that calculates and returns a single value" without saying the result can be void. One has to read the C# documentation to get a more accurate version.
 
I don't think that's correct cjard. I might be missing something because I'm certainly no expert when it comes to lambda expressions, but as far as I'm aware a lambda expression in VB MUST return a value. In C# this is legal:
VB.NET:
private void Form1_Load(object sender, EventArgs e)
{
    System.Threading.Thread t = new System.Threading.Thread(() => DoSomething());

    t.Start();
}

private void DoSomething()
{
}
but in VB this will cause a compilation error:
VB.NET:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim t As New Threading.Thread(DirectCast(Function() DoSomething(), Threading.ThreadStart))

    t.Start()
End Sub

Private Sub DoSomething()

End Sub
This, on the other hand, has no issues at either compile time or run time:
VB.NET:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim t As New Threading.Thread(DirectCast(Function() DoSomething(), Threading.ThreadStart))

    t.Start()
End Sub

Private Function DoSomething() As Object
    Return Nothing
End Function
So, in VB, a lambda expression MUST return a value and, therefore, cannot possibly match the signature of the ThreadStart delegate, yet such an expression CAN be cast as type ThreadStart. In C# it will work whether the lambda expression returns a value or void. I'm still not quite getting how that's logical. I'm guessing there's a simple explanation for it but I'm not seeing it.
 
Back
Top