You don't typically see Windows and Real Time in the same sentence. However, there can be some significant advantages to doing real time signal processing under Windows. This post was inspired by several questions posted on StackOverflow that got closed. I think they were good questions but they don't allow for succinct answers and that seems to violate the monitors sensibilities so I thought a longer form blog post might help some of those questioners.
You say Tomato I say That's not Real Time
So the first question is what's real time? It's a surprisingly hard thing to meaningfully define for the uninitiated but I'm going to try. The primary requirement is that the system exhibit a certain amount of deterministic behavior. This means, that if you need say micro second level responses, that the system reliably and repeatedly will give you microsecond level responses. It can't honor microsecond level timing "most" of the time but every now and then go off to service a daemon or a garbage collector and be gone for 50-100 milliseconds. So at the microsecond level it would appear Windows doesn't cut it, but in fact there are hardware ways around this problem. On the other hand if your real time requirement is hundreds of milliseconds Windows may be suitable without assistance. You might have to disable a lot of services (ala gamers) and you might need to take care with some garbage collected languages but it could easily work. If you need response time in the tens of milliseconds but the occasional hiccup isn't a problem, then I don't think of that as real-time, but again unadorned Windows may suffice. What follows is addressing the solution to the microsecond level deterministic requirement.
The Hardware Solution
The solutions I'm most familiar with are offered by Innovative Integration. II has a series of cards that plug into the PCI backplane that can do a variety of functions and contain FPGAs so you can extend them to do exactly what you want. The cards contain enough buffering that even if the hosting OS is busy for hundreds of milliseconds (or possibly even longer) no data will be lost. This is critical in many of the radar applications I have written. In those applications I will know where the data starts and keeping track of things like the elevation and azimuth angles is done simply by counting the data. A dropped packet would invalidate the entire run. The systems I 've worked on using the Innovative Integration cards have never dropped data and proven to be extremely reliable. The most recent systems I've developed have used their ePC solution. The signal processing happens on a separate computer running Windows XP (the box comes with XP embedded but limitations on .NET and XP Embedded led us to upgrade the OS).
Integrating With Windows
The real-time stuff is being handled by PCI cards or a separate Windows computer with similar hardware. How does one solve the impedance mismatch between Windows timing and the real-time performance of the hardware? A lot depends on the problem you are trying to solve. If as in my case you are collecting radar data, it is the collection of the data, not the display of the data that is critical. I design my systems to make the first priority to store all the data to the hard drive. The next priority is to stream the data out the TCP port for display or additional processing. At this point I can tag the data with elevation and azimuth information so dropping chunks of data is not catastrophic. In fact the typical system collects way more data than a human can analyze in real time so there often is no problem in decimating the data stream being sent to the display.
C++/CLI to the rescue
The biggest problem can be the tools you use. The libraries for a real time system are typically going to be written in a systems level language (a language that compiles to the metal) like C++. Writing your control software in C# can provide some interesting challenges when talking to those libraries. A particular pain point can be the handling of events. I found it impossible to wire up C# event handlers to the C++ events. However, writing thin wrappers in C++/CLI proved to be extremely beneficial. C++/CLI has a lot of facilities for bridging the gap between the managed world of .NET and the unmanaged world happening in the C++ libraries. Originally, I wrote a lot of code in C++/CLI but as grateful as I am for the language and its features I found the code I wrote in C++/CLI required more knowledge and sophistication to maintain properly. Eventually I migrated as much code as I could to C# and left the C++/CLI as the minimal wrapper. In the end this solution worked very well.
There are alternate solutions as well. In fact II provides example solutions written for three environments, Visual Studio (straight VC++), Borland C++ Builder (again straight VC++) but BCB has C# like form designers (I should really say that C# has BCB like tools). They also have examples using the Qt framework.
WCF also Helps
In the case of the ePC where all the processing is happening on a separate computer (usually headless and rack-mounted), I found that a simple WCF service was quite helpful. My GUI was written in C# on a remote computer on the LAN. Every change on the GUI was sent to the WCF service. The service also ran through a series of radar equations and modified dependent parameters. The dependent parameters were then updated on the GUI. It turns out that connecting to the WCF and making the first call is slow, but every call thereafter is quite fast. I made sure the first call happened during the boot phase. After that, users of the system had no idea a remote service was involved. The updating of the screen appeared in "real time" to the user (note that humans aren't microsecond sensitive creatures for the most part).
Plotting the Results
While the .NET world offers a lot of plotting packages, I had trouble finding any that bill themselves as "real time", or even near real time or anything but static. I needed a fast dynamic PPI (polar) plotting capability. We were already using MatLab for the FPGA programming and it turns out MatLab plotting is very fast and proved to be capable of sustaining the frame rates needed by the system. Again, I wrote the low-level code in MatLab's native language (using the object oriented variant helped). I then wrote wrappers to all the MatLab calls in C# and integrated the plotting window into my main C# GUI. Both the GUI and a plot of some synthetically generated data can be seen in the figure to the left.