I get async/await (at least I like to think I do), but I’d like to talk about some conceptual stuff for multi-threaded apps.
I have a port that can send and receive data. It could be TCP, UDP, USB, RS232, whatever.
Back in the old .NET “Framework” days, the read/write methods would just raise an event when new data arrived or when data was sent. Easy then to put the read/write routines into a Background Task and have them sit waiting for data to arrive from the port or for data to be sent to the port and happily not affect the UI thread except when the UI thread subscribed to these events (through a little trickery I learned early on about allowing cross-thread communication)
Seems in .NET now, that I don’t hear much about “Events” anymore. So… If I had a Task running that was waiting for data to arrive, should it raise an Event when there’s new data? Should I use an IObservable? Or perhaps should I set a ManualResetEvent that would stop and start the handler?
Several ways to skin a cat, thoughts on what’s the “best” or at least the most modern way of doing things?
I’m afraid I can’t be much help despite many years working with C#. I have taken the general approach that async complicates things in, shall we say, interesting ways unless there’s a clear use case for it I tend to do without, or, I do the drop dead simple thing and make something an exe or windows service that can just be called and sent on its way to do something. For my particular needs (everything is back end processes and services) I find that adequate. Yes there is occasionally a place where I could do async DB update calls for parts of a complex update that can run separately … but there’s no actual performance issue for me in real world terms. I could probably use async/await in a couple of other places such as loading static in-memory collections, if I were loading them all in advance, but I’m not, I’m lazy-loading them as & when needed.
From what I have read, when I reach the inevitable point where I am forced to do async stuff, I’m inclined to use Task.Run() and variants anyway. But then my use case is different from yours … you want to orchestrate bits of data coming and going at unpredictable intervals, talking to hardware ports. You’ve got a reason to get into the weeds that I don’t. Sadly most of what is written out there leans more to things I might need multi tasking for … getting time-consuming things off the main thread. I don’t typically encounter people writing about event-driven async, either.
Thank you for your reply.
You’re correct that most people don’t have a need to do the sort of things I do, thus the problem with finding out the best way. In the past, I pretty much had to do things by trial and error until it worked the way I wanted. I ended up writing my own MIDI handler before there was anything like that written for .NET, but now I figure if I can think of it, it’s probably been done!
I always have a need for programs to be efficient, and never doing anything that can negatively affect the UI, and certainly never missing data or slowing down communication.
I guess I could try each method, but I wouldn’t mind hearing how others would tackle something like this.
Having never used IObservable, but reading that it might be “the way”, makes me curious. And using ManualResetEvents to keep threads from spinning doing nothing is something I’ve done, but never really been sure whether it was needed. Does a thread that’s just
Task.Run(() =>
while (true)
{
}
);
waste resources? I would think it does, but maybe not?
For those following along, IObservable is part of the “Rx” library, but it’s quite old. Not sure if it’s a deprecated methodology now, but in reading about it, it seems like it might be a good way to announce when new data arrives.
Like you, I’d be inclined to think it would waste resources. Intuitively it does not seem like you’d want to just sit and poll or wait for something to do. A task should be just what its name suggests … something specific to do, starting at the beginning, proceed until you come to the end, and then stop – while the main thread continues on its merry way.
Any need to communicate between the two in real time would be a huge complication, although it’s an interesting problem to ponder.
BTW best practice as I understand it is to use Task.Run() to call an implementation, but not to be used within the implementation (not to be used in reusable library code).
BTW I assume you’ve seen this already but put hit here for the benefit of others who may be curious. It doesn’t address your scenario but it is a decent overview of async in C#.
The communication runs with the variables which are changing. For this you will need a further one: a write marker boolean. When writing the variable first set the boolean to true, write the variable and then set the boolean to false. Read the variables only when the boolean is false. Only possible way. For this mostly you may need to adapt also an interim storage for the needed runtime data in this case for exactly storing a local copy of the variable.
That’s close to the best practice in RTOS and prohibits from glitches reading a variable when it is soon or now been written. Not that complex to have this glitch free in a good behavior.
Yeah, quite familiar with Async/Await and sadly when you look into Async programming, that’s all they talk about.
But, that’s for a background task that will eventually finish. My scenario is different. A background task that runs as long as the program is running. Reading in data and letting the main program know when there’s new data.
IObservable looks like it was kinda “made” for this, but I haven’t really grokked how to implement it properly, even after reading the stuff I linked and several other things on the 'net.
I can’t figure out if it’s making a collection of values or what.
I may have to just bite the bullet and give it a try to see if I can make sense of it…
It will waste resources, it should be put to sleep and notified to wake up only when there is a work to do.
I like how the 8th handles multithreading. You can easily create tasks and wait for tasks to complete. Every task also includes a queue, you can push items onto another tasks queue and notify task that there is a work to do. If there is a need to lock item or variable, a simple spin lock is all you need. You can also easily send stuff onto main GUI task for processing eliminating the need for complex locking when GUI needs to be updated.
I am currently writing a dashboard style GUI for my home automation. It will run on tablets, phones and desktop.
I don’t have any experience of C# beyond playing with it but I’ve done something similar to what you’ve described using PureBasic so I’ll outline how I did that in case it helps:
A global map ( hash table ) of structures that represent the data to be shared between threads. In the case of a network server running in a thread an element in the map might be a structure representing one client request.
A Mutex used by any thread that reads / writes to the map to make sure it’s only ever being accessed by one thread at a time ( PureBasic makes this pretty seamless as if you call LockMutex(MyMutex) and a lock already exists the procedure will just pause and wait until it can obtain the lock then continue ).
A custom event triggered by the secondary thread once it’s acquired / generated any data the main thread needs to look at.
An event listener on the main thread for handling the custom event described above.
lol, that’s from 11 years ago! I was doing that style back in .net4 framework.
Currently interested to find out the best modern way to notify from the background task to the main thread. Events? Observables?
I can start & pause the background threads with ManualResetEvents, and CancellationTokens for ending the thread, so I think that will be best for that, unless someone has other suggestions?