I want to implement a timeout in my UDP Multicast receiver using VB.Net. Basically, if I don't receive any packets in 10 seconds I want to stop listening. I can very easily use a Timer with an interval of 10000 to know when I need to time out, but the question is how do I stop the receive function? If I use the Receive() function (the one that blocks), I could simply stop it with a Thread.Abort() call. Everything I have read, however, has said that this is not a safe practice. If I use the asynchronous BeginReceive() function, I don't know how to terminate it before it finishes normally because EndReceive() will throw an exception if it isn't called with an IASyncResult that is returned from BeginReceive().
The answers to this question led me to investigate the CancelAsync() method. But, the answer to this question made me nervous.
If I use the blocking receive, I will not be able to continuously poll the CancellationPending property unless I call Receive() in its own thread from within the DoWork handler. But that would mean it would continue to run after the cancel takes effect right? If I use BeginReceive(), I am worried that CancelAsync() wil get "eaten" by the DoWork handler and I will end up with the same problem.
Plus, this snippet from the BackgroundWorker documentation is less than reassuring...
Be aware that your code in the DoWork event handler may finish its work as a cancellation request is being made, and your polling loop may miss CancellationPending being set to true. In this case, the Cancelled flag of System.ComponentModel.RunWorkerCompletedEventArgs in your RunWorkerCompleted event handler will not be set to true, even though a cancellation request was made.
One alternative I thought of was having the UdpClient that is sending the packets be in charge of timing out, and then have it send some kind of cancellation signal packet to indicate that the receiver(s) should stop listening. The problem with this is that given the nature of UDP, there is no guarantee that said packet will arrive, or be picked up in the correct order.
Is there a way to safely terminate a UDP receive procedure before it finishes?
I have ran into the same issue with UdpClient and I am not sure what the safe solution is/if a "safe" solution exists. However, I came across a function that a user posted for a different question which tracks and terminates a code block that exceeds a certain time span and I just wrap my call to UdpClient.receive() in it. If you would like to give it a try, the function looks like this:
private static bool TrackFunction(TimeSpan timeSpan, Action codeBlock)
{
try
{
Task task = Task.Factory.StartNew(() => codeBlock());
task.Wait(timeSpan);
return task.IsCompleted;
}
catch (AggregateException ae)
{
throw ae.InnerExceptions[0];
}
}
And you would simply wrap it around your code like such:
bool timeTracker = TrackFunction(TimeSpan.FromSeconds(10), () =>
{
Byte[] received = myUdpClient.Receive(ref myIPEndPoint);
}
Again, there may be a better solution, but this is just what I have used.
I've run in to a similar situation where I open several connections (Udp, Serial, etc.) with remote devices and need to switch among them in a "listener" thread that uses the blocking UdpClient.Receive() call. Calling Thread.Abort() caused crashes, switching the connection instance (the UdpClient) without first exiting the thread didn't work either, because the thread was hung on the UdpClient.Receive() and a simple flag in a while loop never exited.
What did finally work was to close the connection in the main application thread, this would cause UdpClient.Receive() to throw an exception that could be caught and dealt with. The application creates instances of UdpClient that represent the various connections and starts a "listener" thread that can be terminated by setting a global flag and closing the current UdpClient instance. I used VB.NET and it looked something like this:
Dim mListening as Boolean 'application flag for exiting Listener thread
Dim mReceiver as UdpClient 'a connection instance
...
Private Sub Listener()
While mListening
Try
Dim reply = mReceiver.Receive()
Catch ex As Exception
'execution goes here when mReceiver.Close() called
End Try
End While
End Sub
The app sets mListening and starts the Listener thread.
When the app needs to "unblock" mReceiver, it calls mReceiver.Close() and handles it accordingly. I've used this scheme without any problems. I'm using VS 2019 and .NET v4.7
Related
I'm working on a project using a STM32F446 with a boilerplate created with STM32CubeMX (for peripherals initialization and middleware like the FreeRTOS with the CMSIS-V1 interface).
I have two threads which communicate using mailboxes but I encountered a problem: one of the thread body is
void StartDispatcherTask(void const * argument)
{
mailCommand *commandData = NULL;
mailCommandResponse *commandResponse = NULL;
osEvent event;
for(;;)
{
event = osMailGet(commandMailHandle, osWaitForever);
commandData = (mailCommand *)event.value.p;
// Here is the problem
osDelay(5000);
}
}
It gets to the delay but never gets out. Is there a problem with using the mailbox and the delay in the same thread? I tried also bringing the delay before the for(;;) and it works.
EDIT: I guess I can try to add more detail to the problem. The first thread send a mail of a certain type and then waits for a mail of another type; the thread in which I get the problem receive the mail go the first type and execute some code based on what it receive and then send the result as a mail of the second type; sometimes it is that it has to wait using osDelay and there it stop working but without going into any fault handler
I would rather use standard freeRTOS API. ARM CMSIS wrapper is rubbish.
BTW I rather suspect osMailGet(commandMailHandle, osWaitForever);
the delay is in this case not needed at all. If you wait for the data in the BLOCKED state the task does not consume any processing power
If another guesses are:
You are landing in the HF
You are stacked in the context switch (wrong interrupt priorities )
use your debugger and see what is going on.
osStatus osDelay (uint32_t millisec)
The millisec value specifies the number of timer ticks.
The exact time delay depends on the actual time elapsed since the last timer tick.
For a value of 1, the system waits until the next timer tick occurs.
=> You have to check whether timer tick is running or not.
check this link
As P__J__ pointed out in an earlier answer, you shouldn't use the osDelay() call in the loop1
because your task loop will wait at the osMailGet() call for the next request/mail until it arrives anyhow.
But this hint called my attention to another possible reason for your observation, so I'm opening this new answer:2
As the loop execution is interrupted by a delay of 5000 ticks - could it be that the producer of the mails is filling the mailbox faster than the task is consuming mails? Then, you should inspect if this situation is detected/handled in the producer context.
If the producer ignores "queue full" return values and discards the mails before they have been transmitted, the system will only process a few mails every 5000 ticks (or it may lose all but a few mails after the first fill of the mailbox, if the producer in your example only fills the mailbox queue once).
This could look like the consumer task being stuck, even if the main problem is about the producer context (task/ISR).
1
The osDelay() call can only help you if you want to avoid to process another mail within 5000 ticks if request mails are produced faster than the task processes them.
But then, you'd have a different problem, and you should open a different question...
2
Edit: I just noticed that Clifford already mentioned this option in one of his comments to the question. I think this option must be covered by an answer.
I'm developing a tiny UDP console to send some data to test some GPRS devices so I modify an example that I found in CodeProject that it uses one thread; but I get an issue when I want to exit the application, the treahd refuses to stop even if I do something like
If UdpOpen Then
ThreadReceive.Abort()
Me.Dispose()
UdpOpen = False
End If
It halt on the first code line
Private Sub UdpReceive()
Dim receiveBytes As [Byte]() = receivingUdpClient.Receive(RemoteIpEndPoint) '<--Halt here
IpRemote(RemoteIpEndPoint.Address.ToString)
Dim BitDet As BitArray
BitDet = New BitArray(receiveBytes)
Dim strReturnData As String = System.Text.Encoding.ASCII.GetString(receiveBytes)
If UdpOpen Then
StartUdpReceiveThread(CInt(RemotePortLbl.Text))
End If
PrintLog(strReturnData)
End Sub
So I do some research and found, usually, in this Web page the solution
Stop a thread that prevents program to close?
And, as says on the first comment, I turn to True the isBackground property and it work, now the question is Why?
Does somebody knows more in deep how it works?
A thread is only abortable when the CLR knows that it is safe to do so. Which will not be the case when the thread is buried deep inside an operating system call. That is fundamentally unsafe since the CLR cannot know if the thread has acquired any internal operating system locks that need to be released again.
By setting the IsBackground property to true, you tell the CLR that it is okay for the thread to not be aborted but leave it up to the operating system to clean-up anything that needs to released. Any taken locks cannot cause any problems anymore since there is no way for any code to run anymore that could deadlock. The operating system takes care of releasing the OS resources used by the socket. Much as it does if your program aborts for any other reason, like you terminating it with Task Manager.
The proper way to do this is to just call the socket's Dispose() method. That pulls the floor mat on the operating system call, it will stop waiting for anything to be received because the socket is a dead parrot. The Receive() call will complete with an ObjectDisposedException, be prepared to catch it.
Another very common scenario is to not use a thread at all but to use BeginReceive(). Cleanup works much the same way, when you call Dispose() then the callback will run. When you call EndReceive() then you get the ObjectDisposedException. Same way, be prepared to catch it and get out quick without doing anything else with the socket.
Using Thread.IsBackground is otherwise a pretty reasonable way to deal with shutdown, assuming you don't have to do anything intricate to tell the program on the other end of the wire that you stop listening for messages.
.NET has built-in support for receiving UDP asynchronously. See this:
UdpClient.BeginReceive
So you don't need to use threads in this case.
I used SocketClient.cs from this thread and very similar from msdn.
Can somebody tell me why buffer is empty after packets are received?
I have host aplication on windows 8, and then i send from Phone packet with some kind of information. Then host reply to me with new packet. Method 'Receive' receives empty information. Buffer is empty. How to fix that?
If you are not reacting to the Completed event of the SAEA object, no data has been received. If you are, then you received an empty message or your buffersize was 0. This is what the docs are telling you.
I had a look at the code in your link and found that it is using a ManualResetEvent with the SendToAsync method. I don't know why it is doing this but it may be one cause, depending on the timeout specified.
I guess not everyone is reading through the docs for the SAEA object, but you have to think about it as a thread synchronization object. It is sent to a thread, does its work there and signals finish, that just it. Maybe this is the issue with the code in your linked post, the thread that should receive the signal from the SAEA object is busy till the Reset method is called. If so, no event from the SAEA object that is working in another thread is getting through.
Also note that SendToAsync may return immediately with false if the result is available at the time of the call. You can examine the result right away. So you would safely call it like
if (!_socket.SendToAsync(myEventArgs))
ProcessResult(myEventArgs);
So the basic idea is: If you use the SocketAsyncEventArgs, don't use threading. The Async socket methods try to make the threading transparent to the user, and you would just add a threading layer on top of this. This is likely to get you in trouble.
in my Cocoa project, I communicate with a device connected to a serial port. Now, I am waiting for the serial device to send a particular message of some bytes. For the read operation (and the reaction for once the desired message has been received), I created a new thread. On user request, I want to be able to cancel the thread.
As Apple suggests in the docs, I added a flag to the thread dictionary, periodically check if the flag has been set and if so, call [NSThread exit]. This works fine.
Now, the thread may be stuck waiting for the serial device to finally send the 12 byte message. The read call looks like this:
numBytes = read(fileDescriptor, buffer, 12);
Once the thread starts reading from the device, but no data comes in, I can set the flag to tell the thread to finish, but the thread is not going to read the flag unless it finally received at least 12 bytes of data and continues processing.
Is there a way to kill a thread that currently performs a read operation on a serial device?
Edit for clarification:
I do not insist in creating a separate thread for the I/O operations with the serial device. If there is a way to encapsulate the operations such that I am able to "kill" them if the user presses a cancel button, I am perfectly happy.
I am developing a Cocoa application for desktop Mac OS X, so no restrictions regarding mobile devices and their capabilities apply.
A workaround would be to make the read function return immediately if there are no bytes to read. How can I do this?
Use select or poll with a timeout to detect when the descriptor is ready for reading.
Set the timeout to (say) half a second and call it in a loop while checking to see if your thread should exit.
Asynchronous thread cancellation is almost always a bad idea. Try to stick with event-driven interfaces (and, if necessary, timeouts).
This is exactly what the pthread_cancel interface was designed for. You'll want to wrap the block with read in pthread_cleanup_push and pthread_cleanup_pop in order that you can safely clean up if the thread is cancelled, and also disable cancellation (with pthread_setcancelstate) in other code that runs in this thread that you don't want to be cancellable. This can be a pain if proper cleanup would involve multiple call frames; it essentially forces you to use pthread_cleanup_push at every call level and structure your thread code like C++ or Java with try/catch style exception handling.
An alternative approach would be to install a signal handler for an otherwise-unused signal (like SIGUSR1 or one of the realtime signals) without the SA_RESTART flag, so that it interrupts syscalls with EINTR. The signal handler itself can be a complete no-op; the only purpose of it is to interrupt things. Then you can use pthread_kill to interrupt the read (or any other syscall) in a particular thread. This has the advantage that you don't have to switch your code to using C++/Java-type idioms. You can handle the EINTR error by checking a flag (indicating whether the thread was requested to abort) and resume the read if the flag is not set, or return an error code that causes the caller to clean up and eventually pthread_exit.
If you do use interrupting signal handlers, make sure all your syscalls that can return EINTR are wrapped in loops that retry (or check the abort flag and optionally retry) on EINTR. Otherwise things can break badly.
I am trying to use a separate thread to handle specific events in VB.Net. The idea being that I do not want the main application to be held up if a particular event handler takes awhile to finish. How do I get my main thread loop to suspend the thread while allowing it to handle events when they occur?
When I create a Windows Forms application, there is a UI thread that handles the UI events. I do not imagine that this thread is continuously polling some variable to see if someone has pressed a button. I imagine the thread is suspended until the OS tells it there is something to do. I was trying to figure out how to ensure that my event handlers were not being executed by the UI thread. From what I have read, I can do this by raising the events from a different thread. But what does that thread do while it is waiting for other events, just exit?
I wanted to know how to create a thread that works like the UI thread, only it processes the events I want it to process. I am not sure how events work in .Net. I understand that event handlers are run on the thread that raises the event. I believe that .Net allocates threads from some thread pool to process events such as timer events. I am not clear on how it works, though, and what those threads are doing when they are not handling events.
Based on your comments I can see that what you want can best be solved by using the producer-consumer pattern. With this pattern the consumer thread is constructed and started in such a manner that it spins around a loop indefinitely waiting for items to appear in a queue. A UI thread will use this same pattern to implement its message loop. Here is how it works.
public class DedicatedProcessingThread
{
private BlockingCollection<object> m_Queue = new BlockingCollection<object>();
public Consumer()
{
new Thread(
() =>
{
while (true)
{
object item = m_Queue.Take(); // This blocks until an item appears.
// Do something with item here.
}
}).Start();
}
public void Post(object item)
{
m_Queue.Add(item);
}
}
The magic happens in the Take method. This method is designed to "suspend" (your terminology, not mine) or change the state of the thread to WaitSleepJoin while the queue is empty. Once an item is queued the consuming thread wakes up and the Take method returns the next item. That is the general pattern used in the message loop of a UI thread except instead of queueing plain old object instances Windows is posting System.Windows.Forms.Message values. You could do something similar by posting Delegate instances that would then be processed on the consumer thread once they arrive.
You can have the current thread sleep for a specified amount of milliseconds:
Threading.Thread.Sleep(100)
This will sleep for 1/10sec.
However if you need queued events to happen on the current thread, you can use:
Application.DoEvents()
The primary issue with using DoEvents is you don't know how much work actually gets done so it can be somewhat unreliable depending on what you are trying to accomplish.