Results 1 to 5 of 5

Thread: [2008] Background worker always busy.

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Mar 2008
    Posts
    30

    [2008] Background worker always busy.

    Hi gang,

    I'm using a separate thread to send commands to a TCP client so that if communications hang up for some reason, the UI running in the main thread is still responsive.

    When I have a message to send, I call the background worker like this:
    vb Code:
    1. SmartRelayThread.RunWorkerAsync()

    which runs this simple routine:

    vb Code:
    1. Public Class clsSRB
    2.     Private WithEvents SmartRelayThread As New System.ComponentModel.BackgroundWorker ' The thread general communications will happen in.
    3.     Private RelayBoardTCP As New ClientCom
    4.     Private AsciiRcv As String     'Returned from board
    5.     Private AsciiXmit As String    'To be sent to board
    6.  
    7.  
    8.     Private Sub PanelMeterThread_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles SmartRelayThread.DoWork
    9.  
    10.         SmartRelayThread.WorkerSupportsCancellation = True
    11.  
    12.         ' Transmit the contents of AsciiXmit to the TCP client
    13.         ' The ClientCommunication routine uses the TCP client example right from the help file (NetworkStream.Write).
    14.         AsciiRcv = RelayBoardTCP.ClientCommunication(AsciiXmit)
    15.  
    16.     End Sub

    It works great - the first time. In this case, I know for sure when it works because it causes a relay on my workbench to operate.

    The problem is when I try to send another message, I get the "Background Worker is busy" message. It's ALWAYS busy.

    Am I doing something wrong that causes the background worker to never finish? How can I dispose of this thread so that the background worker is available the next time I need to send a message?

    I've tried cancelAsync and Dispose, but neither works.

    Thanks,

    Roger

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,077

    Re: [2008] Background worker always busy.

    Your BackgroundWorker will be busy until its DoWork event handler completes. The DoWork event handler will not complete until the ClientCommunication method returns. Does that method return? From your description I would guess that it doesn't.

    Have you read what CancelAsync does? I can only assume not. You can't just assume that it does what you think it does. As the documentation would have told you, calling that method merely sets a flag. It's up to you to test for that flag in the DoWork event handler and, if it's set, exit the method and, thereby, terminate the background task.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Mar 2008
    Posts
    30

    Re: [2008] Background worker always busy.

    I did read that documentation, as well as the examples Google turns up. It all assumes there is a loop going on inside the background worker that needs to be broken if a cancel request is made. I have no such loop. I'm transmitting a command and waiting for the response. The function called by the background worker returns the response from the client and that works, so I'm not sure why the background worker doesn't complete.

    I simplified the code for troubleshooting, I'll repost to hopefully give you more insight to what is happening.

    Here is where it starts:

    vb Code:
    1. Public Function SendMessage(ByVal msg As Integer) As Boolean
    2.  
    3.  
    4.         'Test to see if background worker is busy.
    5.         If SmartRelayThread.IsBusy = True Then
    6.             SmartRelayThread.CancelAsync()
    7.  
    8.             'If its busy wait until its not.
    9.             Do Until SmartRelayThread.IsBusy = False
    10.                 Thread.Sleep(500)
    11.             Loop
    12.  
    13.         End If
    14.  
    15.         ' Build the appropriate ASCII Text Command.  The BuildCommand function will store the command in the variable AsciiXmit
    16.         BuildCommand(msg)
    17.  
    18.         ' Call the background worker.
    19.         SmartRelayThread.RunWorkerAsync()
    20.  
    21.         Return True
    22.        
    23.  
    24.     End Function

    Now the background worker:

    vb Code:
    1. Private Sub PanelMeterThread_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles SmartRelayThread.DoWork
    2.  
    3.         SmartRelayThread.WorkerSupportsCancellation = True
    4.  
    5.         ' This If block seems completely unncecessary to me because the sub is going to exit anyway after the previous iteration.
    6.         If SmartRelayThread.CancellationPending = True Then
    7.             e.Cancel = True
    8.             Exit Sub
    9.         End If
    10.  
    11.         ' Transmit the contents of AsciiXmit to the TCP client and store the result in AsciiRcv.
    12.         AsciiRcv = ClientCommunication(AsciiXmit)
    13.  
    14.     End Sub

    To actually write to the TCP client, the background worker is calling this function:

    vb Code:
    1. Public Function ClientCommunication(ByVal TCPMsg As String)
    2.        
    3.         ' Translate the passed message into ASCII and store it as a Byte array.
    4.         Dim data As [Byte]() = System.Text.Encoding.ASCII.GetBytes(TCPMsg)
    5.  
    6.         ' Send the message to the connected TcpServer.
    7.  
    8.         TargetTCPClientStream.Write(data, 0, data.Length)
    9.  
    10.         ' Receive the TcpServer.response.
    11.         ' Buffer to store the response bytes.
    12.         data = New [Byte](256) {}
    13.  
    14.         ' String to store the response ASCII representation.
    15.         Dim responseData As [String] = [String].Empty
    16.  
    17.         ' Read the first batch of the TcpServer response bytes.
    18.         Dim bytes As Int32 = TargetTCPClientStream.Read(data, 0, data.Length)
    19.         responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes)
    20.  
    21.         Return responseData
    22.  
    23.     End Function

    I appreciate any insight you can provide me.

    Thanks,

    Roger

  4. #4
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,077

    Re: [2008] Background worker always busy.

    Quote Originally Posted by AegisSailor
    I did read that documentation, as well as the examples Google turns up. It all assumes there is a loop going on inside the background worker that needs to be broken if a cancel request is made.
    It assumes no such thing. The principle is that you must test the CancellationPending property of the BackgroundWorker intermittently to determine whether the user has requested a cancellation. Whether those tests occur in a loop or not, or even whether they occur within the DoWork event handler itself or not, is irrelevant. They just need to occur.

    Now, if all you do in your DoWork event handler is call one asynchronous method then obviously you can't test the CancellationPending property inside the DoWork event handler. Unless you can test it inside the ClientCommunication method you simply cannot cancel the operation. You can't cancel asynchrounous methods.

    The answer for you is probably to not use a BackgroundWorker at all. There's no rule that says you have to. BackgroundWorkers make simple multi-threading scenarios easier. If your scenario goes beyond the somple though, you don't try to force the BackgroundWorker to fit. You just don't use it. Either use the ThreadPool class explicitly, which the BackgroundWorker does implicitly, or else create a Thread object yourself. You can then just start a new thread each time instead of trying to use the same BackgroundWorker every time.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  5. #5

    Thread Starter
    Junior Member
    Join Date
    Mar 2008
    Posts
    30

    Re: [2008] Background worker always busy.

    Fair enough. I guess I was trying to put the square peg in the round hole. Thanks for your help.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width