none
Using Invoke in Application Class RRS feed

  • Question

  • Hi,

    I'm trying to understand how to work with multithread applications by writing some code for an Application in WPF VB. I use a Serial Coms port which runs on it's own thread. I have also created my own Main Window with a stack panel and a TextBlock for showing the received serial data.  The Serial Port and Main Window work fine, however the problem I face is that after setting up a Delegate, the "Invoke" keyword is not being recognized by Visual Studio. Am I missing an Imports? Can I even use the Invoke method in an Application class? If so could someone please let me know what the issue is? Many Thanks!

    Regards,

    LH63.

    Friday, February 16, 2018 7:40 PM

Answers

  • Hi Bob,

    After looking into your suggestion further I got things to work by using Me.Dispatcher.Invoke(UpdateWindowDelegateCall) - so thanks for that!

    Regards,

    LH63

    • Marked as answer by LH63 Saturday, February 17, 2018 12:02 PM
    Saturday, February 17, 2018 12:01 PM

All replies

  • HI LH63,

    In WPF, You need get the Dispatcher associated with the UI element first .

    Try:

                this.Dispatcher.Invoke(() => { });

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Saturday, February 17, 2018 1:57 AM
    Moderator
  • Hi Bob,

    Thanks for the reply but I'm not sure about the syntax of your suggestion and how this would fit in with my code. Below is the code I'm working with but there seems to be an issue with the Me.Invoke(UpdateWindowDelegateCall ).  As I mentioned Visual Studio doesn't seem to recognize the Invoke command. I would appreciate if you could review my code and comment please. Many Thanks!

    Imports System.IO.Ports
    
    Class Application
    
        Private Delegate Sub UpdateWindowDelegate()
    
        Private UpdateWindowDelegateCall As UpdateWindowDelegate
    
        Private my_serialport As New SerialPort
    
        Private RxBuffer As Byte()
    
        Private my_TextBlock1 As New TextBlock
    
        Private Sub Application_Startup(sender As Object, e As StartupEventArgs)
    
            UpdateWindowDelegateCall = New UpdateWindowDelegate(AddressOf UpdateWindow)
    
            With my_serialport
                .PortName = "COM1"
                .BaudRate = 9600
                .DataBits = 8
                .StopBits = 1
                .Parity = Parity.None
            End With
    
            AddHandler my_serialport.DataReceived, AddressOf my_SerialPortDataReceivedEvent
    
            my_serialport.Open()
    
            Dim my_MainWindow As New Window
            Dim my_StackPanel As New StackPanel
    
            With my_TextBlock1
                .HorizontalAlignment = HorizontalAlignment.Center
                .VerticalAlignment = VerticalAlignment.Center
                .FontFamily = New FontFamily("Arial")
                .FontSize = 35
                .Foreground = New SolidColorBrush(Colors.Black)
                .Text = "TextBlock1"
            End With
    
            my_StackPanel.Children.Add(my_TextBlock1)
    
            my_MainWindow.Content = my_StackPanel
    
            my_MainWindow.Show()
    
        End Sub
    
    
        Private Sub my_SerialPortDataReceivedEvent(sender As Object, e As SerialDataReceivedEventArgs)
    
            UpdateWindowDelegateCall = New UpdateWindowDelegate(AddressOf UpdateWindow)
    
            Dim n As Integer = my_serialport.BytesToRead
            RxBuffer = New Byte(n - 1) {}
    
            my_serialport.Read(RxBuffer, 0, n)
    
            If n = 5 Then
    
                If RxBuffer(0) = &H2 Then
                    Dim i As Byte
                    Dim checksum As UShort
                    For i = 0 To UBound(RxBuffer) - 1
                        checksum = (checksum + RxBuffer(i)) Xor &HFF
                    Next
    
                    checksum = CByte(checksum And &HFF)
    
                    If checksum = RxBuffer(4) Then
    
                    End If
    
                End If
    
            End If
    
            Me.Invoke(UpdateWindowDelegateCall)
    
        End Sub
    
        Private Sub UpdateWindow()
    
            my_TextBlock1.Text = RxBuffer(0)
    
        End Sub
    
        Private Sub Application_Exit(sender As Object, e As ExitEventArgs)
    
            If my_serialport.IsOpen Then my_serialport.Close()
    
        End Sub

    Saturday, February 17, 2018 9:24 AM
  • I wouldn't use the dispatcher associated with a specific control.

    I use:

    Application.Current.Dispatcher.InvokeAsync(new Action(() =>
    {
        // Do something with UI
    }));

    Note that this is asynchronous so you don't block your own thread calling it.

    And, of course, this is c#


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Saturday, February 17, 2018 10:17 AM
    Moderator
  • Hi Bob,

    After looking into your suggestion further I got things to work by using Me.Dispatcher.Invoke(UpdateWindowDelegateCall) - so thanks for that!

    Regards,

    LH63

    • Marked as answer by LH63 Saturday, February 17, 2018 12:02 PM
    Saturday, February 17, 2018 12:01 PM
  • Hi Richard,

    Thanks for the suggestion.  I'm now experimenting with BeginInvoke which is asynchronous. Not sure what the difference is between InvokeAsync and BeginInvoke but will look into it - Many Thanks!

    Regards,

    LH63

    Saturday, February 17, 2018 12:06 PM