-
Sep 4th, 2008, 02:27 PM
#1
Thread Starter
Junior Member
[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:
SmartRelayThread.RunWorkerAsync()
which runs this simple routine:
vb Code:
Public Class clsSRB
Private WithEvents SmartRelayThread As New System.ComponentModel.BackgroundWorker ' The thread general communications will happen in.
Private RelayBoardTCP As New ClientCom
Private AsciiRcv As String 'Returned from board
Private AsciiXmit As String 'To be sent to board
Private Sub PanelMeterThread_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles SmartRelayThread.DoWork
SmartRelayThread.WorkerSupportsCancellation = True
' Transmit the contents of AsciiXmit to the TCP client
' The ClientCommunication routine uses the TCP client example right from the help file (NetworkStream.Write).
AsciiRcv = RelayBoardTCP.ClientCommunication(AsciiXmit)
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
-
Sep 4th, 2008, 06:45 PM
#2
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.
-
Sep 5th, 2008, 11:37 AM
#3
Thread Starter
Junior Member
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:
Public Function SendMessage(ByVal msg As Integer) As Boolean
'Test to see if background worker is busy.
If SmartRelayThread.IsBusy = True Then
SmartRelayThread.CancelAsync()
'If its busy wait until its not.
Do Until SmartRelayThread.IsBusy = False
Thread.Sleep(500)
Loop
End If
' Build the appropriate ASCII Text Command. The BuildCommand function will store the command in the variable AsciiXmit
BuildCommand(msg)
' Call the background worker.
SmartRelayThread.RunWorkerAsync()
Return True
End Function
Now the background worker:
vb Code:
Private Sub PanelMeterThread_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles SmartRelayThread.DoWork
SmartRelayThread.WorkerSupportsCancellation = True
' This If block seems completely unncecessary to me because the sub is going to exit anyway after the previous iteration.
If SmartRelayThread.CancellationPending = True Then
e.Cancel = True
Exit Sub
End If
' Transmit the contents of AsciiXmit to the TCP client and store the result in AsciiRcv.
AsciiRcv = ClientCommunication(AsciiXmit)
End Sub
To actually write to the TCP client, the background worker is calling this function:
vb Code:
Public Function ClientCommunication(ByVal TCPMsg As String)
' Translate the passed message into ASCII and store it as a Byte array.
Dim data As [Byte]() = System.Text.Encoding.ASCII.GetBytes(TCPMsg)
' Send the message to the connected TcpServer.
TargetTCPClientStream.Write(data, 0, data.Length)
' Receive the TcpServer.response.
' Buffer to store the response bytes.
data = New [Byte](256) {}
' String to store the response ASCII representation.
Dim responseData As [String] = [String].Empty
' Read the first batch of the TcpServer response bytes.
Dim bytes As Int32 = TargetTCPClientStream.Read(data, 0, data.Length)
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes)
Return responseData
End Function
I appreciate any insight you can provide me.
Thanks,
Roger
-
Sep 5th, 2008, 11:21 PM
#4
Re: [2008] Background worker always busy.
 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.
-
Sep 8th, 2008, 03:03 PM
#5
Thread Starter
Junior Member
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|