6 Replies - 14379 Views - Last Post: 05 March 2018 - 04:18 AM Rate Topic: -----

#1 RDR   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 16
  • Joined: 15-March 09

How to make thread safe calls

Posted 03 April 2010 - 11:04 PM

My application requires a cross thread call to update the contents of a textbox. Trying to do this directly results in the dreaded "illegal cross thread call" exception.
I realise that a delegate is required but I cannot find a simple, plain english example to explain how to do this. All the examples and "help" files that I read are very cryptic and confusing.
Here's what I need:
The application responds to a DataReceived event (on the serialport), reads the data into a byte array, converts the two bytes into a word, converts to string and displays to a textbox. Here is some of the code:

For bnum = 0 To 19
SerialPort1.Read(sdata, bnum, 1)
Next bnum
SerialPort1.Read(sadj, 0, 16)
flags1 = sdata(19)
lhighbyte = sdata(0)
llowbyte = sdata(1)
lrpm = (lhighbyte * &H100) Or llowbyte
RpmLabel.Text = (CStr("RPM " & lrpm))

The problem of course is the last line is a cross thread call.
How do I set up the delegate call (exactly please).
Note that RpmLabel was not created on another thread, rather it was a drag-and-drop from the toolbox onto the form.

Is This A Good Question/Topic? 0
  • +

Replies To: How to make thread safe calls

#2 Asscotte   User is offline

  • D.I.C Addict
  • member icon

Reputation: 35
  • View blog
  • Posts: 610
  • Joined: 08-February 09

Re: How to make thread safe calls

Posted 04 April 2010 - 05:50 AM

Okay well depending on how you want to do this you could either use a "Delegate" or you could cheaply abuse a local variable :), which would be a loop to check if the value has changed and if it has do whatever with it.

Next time you post please could you use the code tags :)
Was This Post Helpful? 0
  • +
  • -

#3 PsychoCoder   User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1659
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Re: How to make thread safe calls

Posted 04 April 2010 - 06:49 AM

Since you cannot access a UI element from a thread other than the one that created it, without some work. You could do as already pointed out and use a delegate, or you could take a loook and how to use it.

First an Extension method to take care of your Invoke for you

public static class SynchronizeInvoke
{
    public static void CustomInvoke<T>(this T @control, Action<T> toPerform) where T : ISynchronizeInvoke
    {
        if (@control.InvokeRequired)
            @control.Invoke(toPerform, new object[] { @control });
        else
            toPerform(@control);
    }
}



To use it take a look at this example (using your code)

For bnum = 0 To 19
SerialPort1.Read(sdata, bnum, 1) 
Next bnum
SerialPort1.Read(sadj, 0, 16)
flags1 = sdata(19) 
lhighbyte = sdata(0)
llowbyte = sdata(1) 
lrpm = (lhighbyte * &H100) Or llowbyte 
RpmLabel.CustomInvoke(l => l.Text = (CStr("RPM " & lrpm)))



That will take care of your cross-thread exception

EDIT: Sorry that code is for C#, forgot this is the VB.NET forum. To make that code work with VB.NET you need a module that looks like this

Imports System.ComponentModel
Imports System.Runtime.CompilerServices

Public Module SynchronizeInvoke
    <Extension()> _
    Public Sub CustomInvoke(Of T As ISynchronizeInvoke)(ByVal control As T, ByVal toPerform As Action(Of T))
        If control.InvokeRequired Then
            control.Invoke(toPerform, New Object() {control})
        Else
            toPerform(control)
        End If
    End Sub
End Module



Then it can be used as shown above. Sorry about that :)
Was This Post Helpful? 1
  • +
  • -

#4 PsychoCoder   User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1659
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Re: How to make thread safe calls

Posted 04 April 2010 - 08:57 AM

To help even more take a look at this: Handling the dreaded cross-thread Exception. It covers a couple options you have for handling this :)
Was This Post Helpful? 1
  • +
  • -

#5 RDR   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 16
  • Joined: 15-March 09

Re: How to make thread safe calls

Posted 04 April 2010 - 10:57 PM

View PostPsychoCoder, on 04 April 2010 - 07:57 AM, said:

To help even more take a look at this: Handling the dreaded cross-thread Exception. It covers a couple options you have for handling this :)


Hi PsychoCoder, thanks for your help.
I have now managed to clear up all my cross-thread call problems.
One question though:
Why do cross-thread calls only seem to create a problem when called on the SerialDataReceived event?
I have other cross-thread calls in my application that don't seem to be a problem.
Was This Post Helpful? 0
  • +
  • -

#6 TravisH   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 05-March 18

Re: How to make thread safe calls

Posted 05 March 2018 - 03:52 AM

View PostPsychoCoder, on 04 April 2010 - 06:49 AM, said:

Since you cannot access a UI element from a thread other than the one that created it, without some work. You could do as already pointed out and use a delegate, or you could take a loook and how to use it.

First an Extension method to take care of your Invoke for you

public static class SynchronizeInvoke
{
    public static void CustomInvoke<T>(this T @control, Action<T> toPerform) where T : ISynchronizeInvoke
    {
        if (@control.InvokeRequired)
            @control.Invoke(toPerform, new object[] { @control });
        else
            toPerform(@control);
    }
}



To use it take a look at this example (using your code)

For bnum = 0 To 19
SerialPort1.Read(sdata, bnum, 1) 
Next bnum
SerialPort1.Read(sadj, 0, 16)
flags1 = sdata(19) 
lhighbyte = sdata(0)
llowbyte = sdata(1) 
lrpm = (lhighbyte * &H100) Or llowbyte 
RpmLabel.CustomInvoke(l => l.Text = (CStr("RPM " & lrpm)))



That will take care of your cross-thread exception

EDIT: Sorry that code is for C#, forgot this is the VB.NET forum. To make that code work with VB.NET you need a module that looks like this

Imports System.ComponentModel
Imports System.Runtime.CompilerServices

Public Module SynchronizeInvoke
    <Extension()> _
    Public Sub CustomInvoke(Of T As ISynchronizeInvoke)(ByVal control As T, ByVal toPerform As Action(Of T))
        If control.InvokeRequired Then
            control.Invoke(toPerform, New Object() {control})
        Else
            toPerform(control)
        End If
    End Sub
End Module



Then it can be used as shown above. Sorry about that :)/>



Apologies for bringing up such an old thread. I am using a thread to capture images from a camera for processing and this module looks perfect, but I am not too sure how it would apply to updating a picturebox.

My picturebox is img_src, so I had tried
img_src.CustomInvoke(l >= l.image = bmp_)
but it would give me an error of operator => is not defined for types picturebox and image. Can i ask where the l comes from in your example, and how this could be translated to making a bitmap (e.g. bmp_) the image of a picturebox (img_src).

Keen to better understand this, as I have a lot of threads I will be running in my code which need to update various controls and variables so it would be great to use a tool which does not require me to create delegates for every control I need to set an image or text in, and update or modify.

Many Thanks!
Was This Post Helpful? 0
  • +
  • -

#7 andrewsw   User is offline

  • RequestedRangeNotSatisfiable
  • member icon

Reputation: 6552
  • View blog
  • Posts: 26,562
  • Joined: 12-December 12

Re: How to make thread safe calls

Posted 05 March 2018 - 04:18 AM

By >= presumably you meant => ? However, this =>, is the C# syntax for a lambda, which the author noted above that he had provided in error.

VB.NET Lambda Expressions

However, given the time that has elapsed, please create your own topic for this in the forum. You can include a link to this current topic if you still think it useful for reference.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1