I have written my network code for my app using Sockets. I've tested the library on a windows PC and it is very fast. Whether it's many small "packets" (by packets I mean send operations, I am using TCP which is streaming) of data in a small amount of time, or a few large ones, it works perfectly.
I moved the code into a test app for the iPhone. Ran the test, great speeds again. about 5 MB sent over wifi between two phones in about 3 seconds.
Im using synchronous Socket.Send() operations in a threadpool thread, and using ReceiveAsync() for receiving. (I've also tried the BeginReceive() style, but it behaves the same.
However, once I move the code into my app, I start to encounter problems. The general problem is that the receiving app doesnt seem to receive consistently. I could send several "packets" of data from the host phone, and it can be anywhere from instantly, to a few seconds to 10 minutes before they appear on the receiving end. I've been on this problem for 2 weeks now (evenings/weekends) and i've spent days testing it to try understand exactly what I can do to reproduce it, but its never the same twice.
At the moment, im putting it down to threadpool threads being exhausted. I've used
ThreadPool.SetMaxThreads()
to increase the thread count drastically, but it doesnt make any difference. Its like as if the completed callback in SocketAsyncEventArgs cannot get a thread to operate on, so it just sits there. I've gone through my code and refactored anything that was un-necessarily using threads with a loop performing periodic tasks and changed them to timers, but the problem remains.
I have literally no idea where to turn with this one. Im hoping its maybe a bug in Monotouch (not that Im trying to blame those guys!).
Im not sure what code to post, as the network code has been tested on its own and operates fine. I've tested it with 1,000,000 send/receives to check if there was some kind of leak but found no problems.
It seems like the data is getting to the recipient, but the callback is somehow getting severely delayed in getting called, sometimes by several minutes.
Can anyone point me in a direction of why this might be happening?
Thank you.
My problem with this was caused by having a GKSession also initialized. I hope this is a bug in Monotouch/Mono that can be fixed, as I do need both network features enabled. As soon as i disabled the GKSession, the socket code flows freely.
Related
I've got quite an abstract question. I'm working on a project that requires constant device communication. I'm integrating multiple devices onto an external processing unit with a touchpanel to execute certain methods. I.e. the "start videocall" button on the touchpanel activates a relay, turns a display-device, camera-device and microphone-device on, etc.
On the flipside, I'm also trying to monitor these devices. What status do they currently have? Are they enabled/disabled ? What input is the display device currently on?
So far, I've come up with two solutions to prevent a bottleneck in the communication where I'm constantly polling (i.e. every two to five seconds to keep an acurate and up-to-date status) the on-state and input-state of the display-device.
Make use of threading so I can enqueue the different commands and execute them async. By also reading the response async, all communication should be nicely spaced out but I'd have a very "busy" communication line, taking it's toll on the processing unit.
With the help of events have the display-device notify the processor of it's changed status. This would take a lot of stress off of the communication line, but I feel like this is very easily disrupted. If the device doesn't throw it's events correctly (or the events are missed out on) the monitored state does not correspond with the actual state.
I'm curious if there are other ways of going about this issue. As of now, I'm leaning towards the second one because it stresses the processing unit a whole lot less, I just feel like I should be building in a lot of safeguards to prevent an inacurate representation of the actual device-states.
The project runs in C# on .Net 3.5.
Polling works, but it isn't fun or optimal. Reactive is best but as you've mentioned there may be a hiccup insuring your still listening to to the device and not just standing by for nothing. In this situation it makes since to optimize both processes. Poll when you're waiting or haven't heard a response in so long and listen when your polling returns good info, passing the polling.
That said, you shouldn't worry about taxing the unit too much with polling on various threads. This sounds like a purpose device so as long as you're not running it hot or stressing it to max all the time then using your resources are perfectly fine.
I've read a lot about this topic, but still am not sure what to do.
First, the situation: I have software written in C# using .NET 4.5 that polls up to 64 devices on a CAN network that I communicate with via USB using a third party API from the device manufacturer. The purpose is to provide the user with realtime updates of temperature, pressure, and other values like that from some sensors.
Currently I create a System.Threading.Thread for every device which runs a while loop that queries the device for the relevant info, saves updates to SQL Server via Entity Framework, then sleeps for 1.25 seconds.
This runs ok on smaller systems with ~20 or fewer devices, but on a large install with 50+ devices it runs very slowly. I think that my problem is the overhead of creating so many threads. And it doesn't help that I'm stuck with a crappy Atom processor, although at least this one is quad core unlike the previous system I used that was dual core.
So, I've been trying to make the process more efficient. Everything I read seems to point to Task.Run() being the more effective way of doing something like this, but this software could potentially be running for weeks or months at a time, which I THINK means I would need to run it with TaskCreationOptions.LongRunning. But I've read conflicting things on this, so I'm not sure. But if that is the case, then my understanding is that TPL will just start up a new dedicated thread anyways, so it seems like that would still have the overhead I'm trying to avoid.
So, as you can see, I'm pretty lost on this topic. I don't know if I should just give Task.Run() a try, and see what happens, or if there's a whole different way I should do this.
Any help would be immensely appreciated.
Thank you.
I'm working on a Unity game that receives OSC messages from the Muse EEG headset. I've tried two 3rd party C# libraries to handle the OSC communication, UnityOSC and unity-OSC-receiver. Both implement the OSC communication with an underlying System.Net.Sockets.UdpClient. Everything is running smoothly on Windows, but on OSX, after a while, I just stop receiving messages every time. No exceptions or error messages, no indication of what went wrong at all, just silence.
My application roughly works as follows:
Start a thread that spawns a process that runs Muse-IO. This makes the headset start sending messages. After starting the process, this thread is just chilling on process.WaitforExit()
Another thread runs a while loop - not in MonoBehavior.Update(), that's not fast enough - that keeps receiving and processing OSC messages. In both libraries, this essentially boils down to calling UdpClient.Receive()
Game uses the processed messages in the normal Unity update cycle.
Some 120 to 140 seconds after the connection is initialized, the stream of messages just stops, and so far I haven't been able to figure out why. The connection indicator light on the headset stays on, but nothing indicates it's actually still sending data.
Things I've ruled out:
It's not because the number of messages or the size of the messages. If I modify the command to the headset to only send some categories of messages, cutting the total in half (from about 600/s to 300/s), the timeout still happens at the same time.
It's not the OSC library. I get the exact same results with both OSC libraries.
It's not the firewall. The firewall is off.
It's probably not the port being used by something else. I tried different ports with the same result.
It doesn't appear to be Muse's OSX driver. When I use their GUI to visualize the incoming data, it keeps receiving data for as long as I want.
I suspect that Mono, Unity or OSX might be shutting down (garbage-collecting?) the Muse-IO process or thread, because the time before the problem occurs seems to be pretty much constant regardless of what I try. But I'm unsure how to further diagnose, let alone fix this now. Any clues, suggestions or amazing solutions would be most welcome.
I found the cause.
After spawning the I/O process, the thread would do
print("Process started!");
process.PriorityClass = ProcessPriorityClass.High;
process.WaitforExit();
In hindsight, that print statement is really poorly placed, oh well. It worked fine on Windows. Changing process priority only requires admin privilege if you're increasing it to Realtime, according to the docs. Not so on Mac though. apparently setting it to High also requires elevated rights on OSX. The resulting exception was silent/undetected/uncaught because it happens outside the main thread.
Then, several minutes later, it seems the thread is garbage collected, including its child process, even though that's still running. That delay really threw me off, making me look for the cause in all the wrong places.
Lessons learned:
Be more careful with possible exceptions when multithreading,
Don't mess with process priority if you don't absolutely have to,
And never trust the docs.
While trying to read data from a TCP socket using ReceiveAsync.Completed, I experience a few ms delay (1-5ms, once in a while) between the time the data arrives to my application and the time it arrives to the machine. I use Wireshark to compare the timestamps, PSH bit is turned on for those messages as well and the application is not busy or blocking anything. What am I missing ?
Thanks.
With such a small delay it could come from anywhere, the garbage collector kicking in could delay you that much easily.
Wireshark isn't operating on the same level as your application. It could be that it's getting the data at different times than you just because the system is supplying it a little faster. Or maybe their times are off. Maybe your times are off. With such a small difference its hard to tell.
I bet you're not doing anything wrong.
We have very strange problem, one of our applications is continually querying server by using .net remoting, and every 100 seconds the application stops querying for a short duration and then resumes the operation. The problem is on a client and not on the server because applications actually queries several servers in the same time and stops receiving data from all of them in the same time.
100 Seconds is a give away number as it's the default timeout for a webrequest in .Net.
I've seen in the past that the PSI (Project Server Interface within Microsoft Project) didn't override the timeout and so the default of 100 seconds was applied and would terminate anything talking to it for longer than that time.
Do you have access to all of the code and are you sure you have set timeouts where applicable so that any defaults are not being applied unbeknownst to you?
I've never seen that behavior before and unfortunately it's a vague enough scenario I think you're going to have a hard time finding someone on this board who's encountered the problem. It's likely specific to your application.
I think there are a few investigations you can do to help you narrow down the problem.
Determine whether it's the client or server that is actually stalling. If you have problems determining this, try installing a packet filter and monitor the traffic to see who sent the last data. You likely won't be able to read the binary data but at least you will get a sense of who is lagging behind.
Once you figure out whether it's the client or server causing the lag, attempt to debug into the application and get a breakpoint where the hang occurs. This should give you enough details to help track down the problem. Or at least ask a more defined question on SO.
How is the application coded to implement the continuous querying? Is it in a continuous loop? or a loop with a Thread.Sleep? or is it on a timer ?,
It would first be useful to determine if your system is executing this "trigger" in your code when you expect it to, or if it is, and the remoting server is not responding... so, ...
if you cannot reproduce this issue in a development environment where you can debug it, then, if you can, I suggest you add code to this Loop to write out to a log file (or some other persistence mechanism) each time it "should" be examining whatever conditions it uses to decide whether to query the remoting server or not, and then review those logs when the problem reoccurs...
If you can do the same in your remoting server, to record when the server receives a remoting request, this would help as well...
... and oh yes, just a thought, (I don;t know how you have coded this... ) but if you are using a separate thread in client to issue the remoting request, and the channel is being registered, and unregistered on that separate thread, make sure you are deconflicting the requests, cause you can't register the same port twice on the same machine at the same time...
(although this should probably have raised an exception in your client if this was the issue)