1

Time ago I've seen a multi-threading technique code like this:

Private Delegate Sub TextBoxUpdateUI(ByVal txt As String)

Private t As Threading.Thread = New Threading.Thread(Sub() _
        If tb2.InvokeRequired Then 
            Dim tb_delegate As New TextBoxUpdateUI(AddressOf "This Sub")
            tb2.Invoke(tb_delegate, Text)
        Else
            tb2.Text = tb1.Text
        End If _
)

The thing is that, be able to write some instructions inside the Thread argument, I don't remember well the example that I've seen but if I remember well it used a Lambda like I've tried to use.

But the code above does not work, just I wanted to reproduce it, but I lost the example that I've seen so I don't know exactly how to write it.

Someone can fix the lambda?

Also, at the delegate line in the AdressOf operator how could I fix it to refer to that?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • What about it isn't working? Are you calling `t.Start()`? – Steven Doggart Oct 21 '13 at 12:22
  • @Steven Doggart with "isn't working" I mean that can't be compiled because an exception says that Lambda expression should have one line instance or something simillar message, sorry I can't verify the exception message now. – ElektroStudios Oct 21 '13 at 12:32

3 Answers3

2

There are two syntax styles for lambda expressions in VB.NET: single-line, and multi-line. When you are doing a multi-line expression, you need to actually go to a new line immediately after the Sub or Function declaration. If you don't, it will assume that it is a single-line expression. So, the first problem is that you have a line continuation character after the Sub() _ which means that the following If statement is on the same line as the Sub declaration, so it assumes it is a single-line expression.

The second problem is that when you are writing a multi-line lambda expression, you must end it with an End Sub or End Function statement. Your code is missing that line. So, to fix your code, just change it like this:

Private t As Threading.Thread = New Threading.Thread(Sub()
        If tb2.InvokeRequired Then 
            Dim tb_delegate As New TextBoxUpdateUI(AddressOf "This Sub")
            tb2.Invoke(tb_delegate, Text)
        Else
            tb2.Text = tb1.Text
        End If
    End Sub
    )

It's worth mentioning, however, that this is a terrible example. The only thing that the thread is doing, in this example, is invoking back to the UI thread, which is is, of course, single-threaded, so the extra thread is completely unnecessary. If that's really all you are trying to do--invoke something on the UI thread, but not sit and wait for the UI to process the request--you should just use BeginInvoke instead of Invoke, like this (no new thread required):

If TextBox1.InvokeRequired Then
    TextBox1.BeginInvoke(Sub() TextBox1.Text = "sometext")
Else
    TextBox1.Text = "sometext"
End If
Steven Doggart
  • 43,358
  • 8
  • 68
  • 105
  • Thankyou, so, If I understanded good, the `Invoke` method invokes the action on the main thread, but `BeginInvoke` method creates a new thread or something simillar to run the action, I made ​​a mess, If I want to do a multi-threaded application then in the secondary threads I need to use `Invoke`, or I need to use `BeginInvoke`? – ElektroStudios Oct 22 '13 at 11:29
  • No matter I've found this: http://stackoverflow.com/questions/229554/whats-the-difference-between-invoke-and-begininvoke/ – ElektroStudios Oct 22 '13 at 11:35
  • What about the `AdressOf` operator of this line inside the Lambda?: `Dim tb_delegate As New TextBoxUpdateUI(AddressOf "This Sub")` I would like to set the delegate inside the Lambda instead of doing this else: `tb2.BeginInvoke(Sub() tb2.Text = tb1.Text)` – ElektroStudios Oct 22 '13 at 11:40
  • 1
    I don't know how to get a delegate to the current lambda expression. It would make a good new question. But even if there is a way to do it, I wouldn't recommend it. It would be ugly and confusing. At that point, I'd just use an actual separate method rather than a multi-line lambda expression. – Steven Doggart Oct 22 '13 at 13:30
1

You don't need the thread or the delegate just

    If TextBox1.InvokeRequired Then
        TextBox1.Invoke(Sub() TextBox1.Text = "sometext")
    Else
        TextBox1.Text = "sometext"
    End If
dbasnett
  • 11,334
  • 2
  • 25
  • 33
  • Hi, I know that I can use a Lmanda on the Invoke method, but I would to reproduce the technique that I've seen. Thanks for answer! – ElektroStudios Oct 21 '13 at 11:26
1

You can assign the AddressOf method to the ParameterizedThreadStart using Lambda.

You can also write the TextBoxUpdateUi method inline using sub(), but you have to declare TextBoxUpdateUI delegate.

For example:

Delegate Sub TextBoxUpdateUI(ByVal text As String)

If you want it in Lambda it would be this way:

   Dim MyThread As New Thread( _
            New ParameterizedThreadStart( _
                Sub()
                    If tb2.InvokeRequired Then
                         Dim tb_delegate As New TextBoxUpdateUI(Sub(x)
                                                               'Do your stuff here
                                                               tb1.Text = x
                                                           End Sub)
                        tb2.Invoke(tb_delegate, Text)
                    Else
                        tb2.Text = tb1.Text
                    End If
                End Sub))
Carlos Landeras
  • 11,025
  • 11
  • 56
  • 82