Asynchronous API for Streaming Data from a Hardware Device - c#

I'm writing a library in C#, but I need to make it asynchronous. Normally you expose a set of DLL functions, and they take input parameters, and return a value when finished. But how can I make a library function (callable from C++/Delphi/Etc) that already starts streaming back output while still taking input?
The only solution I see now is to communicate using sockets/pipes/etc, instead of DLL calls.
Does someone have an example how to do this with normal DLL calls?

One good model for a straightforward asynchronous library call (which is located in System.dll) is WebClient.DownloadStringAsync. This method downloads from a Uri asynchronously, and raises the DownloadStringCompleted event whenever it finishes.
Your library could likewise provide a FooAsync method, which doesn't block the current thread but raises a FooDataReceived event whenever some data comes into your library and a FooCompleted event whenever the calculation finishes.

According to the comments from the OP the calling application sends audio to the DLL, the DLL sends audio out via some USB interface, the DLL captures some audio from the mic interface and needs to send the captured audio back to the application while the application sends audio to the DLL etc.
Based on this and the fact that the calling can be written in rahter different languages I see some options for the communication channels:
TCP/IP (depending on "desktop firewall settings" etc. this could be problematic!)
Pipes
COM objects with events/event handlers
DLL with callback although this will be a bit hard to get working for all languages
shared memory with global mutexes (could ease that for the consuming application by offering a "setup" function from the DLL which return the pointers and mutex names)

There are a couple of ways to go with this. In most languages you can make async calls to methods using threads or dispatchers. In general, as long as you make your dll re-entrant (capable of servicing multiple threads at the same time) the calling environment can take care of the async part.
It is possible to bake the async calls into your API, however. An example of something that does this is the WCF client proxies.

Microsoft has a good article on this matter. If you just mover over the EndInvoke, it should work for you as well. http://msdn.microsoft.com/en-us/library/2e08f6yc(v=vs.71).aspx

Since you want both Input and Output to be async, you will need a
worker thread: If neither the inputting thread, nor the one taking
the output can be blocked, both can't be bothered to do the work.
Your already thought of communicating via pipes, but why use a pipe and not an internal strcuture?
So you have this lock-free queue on the input, another one on the output and a worker thread
The worker thread takes input from the inqueue, processes it, puts it into the outqueue
If the input queue becomes empty, the worker thread has nothing to crunch on, so he raises a "need more data" event and then blocks on the input queue becoming (partly) full
If the worker thread puts something in the output queue, he raises a "have more data" event, and if the output queue becomes (fully) full, he blocks on output space becoming available
Your API is nonblocking: Neither sending input nor receiving output ever block
Your API is async: Notifications (via Events) are given

I like the following approach because it makes it really simple for the clients.
// your library
class Foo {
public event EventHandler ComputeCompleted = (sender, e) => { };
public void Compute() {
// kick off work on a background thread
// possibly using the BackgroundWorker object
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += RunWorkerCompleted;
bw.RunWorkerAsync();
}
private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
ComputeCompleted(this, new object());
}
}
// calling code
Foo foo = new Foo();
foo.ComputeCompleted += Completed;
foo.Compute();
private void Completed(object Sender, EventArgs e) {
// process the result here
}
The gist is that you kick off a method in the library that returns right away, then notifies the caller via an event/delegate that the processing is complete. You are then free to Invoke the execution back onto the UI thread as needed.
Obviously, error handling not included in the sample code.

Related

What happens if event occurs again when the first is not finished handling

My Question is about the DataReceived event from an System.IO.SerialPort. I have a method which gets called when that event occurs. I read the Data with myPort.ReadExisting, process it and save it. If I get a specific character the data up to that point is interpreted as command and another event is triggered.
My question is, what happens if I'm in the middle of processing the received Data and new data comes? Is the new instances of the method waiting for the old to finish? If not it could result in a conflict because both instances of that method use the same variables. Am I wrong in the concept of event handling or is there an elegant way to deal with that.
My code is running fine and my results are as expected, but my data processing is not that sophisticated. I just want to understand this issue und avoid getting problems in the future.
My Code example would be this:
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort port = (SerialPort)sender;
int index = m_ports.FindIndex(p => p.PortName == port.PortName);
string tmpData;
m_currentData[index] += tmpData = port.ReadExisting();
Console.WriteLine(tmpData);
string currentData = m_currentData[index];
string currentOrder = "";
while (currentData.Contains(orderEndChar))
{
int endCharLocation = currentData.IndexOf(orderEndChar);
currentOrder = currentData.Substring(0, endCharLocation);
currentData = currentData.Substring(endCharLocation + 1);
orderEvent.gotOrder(currentOrder);
//orderEvent.gotOrder(new EventArgs());
}
m_currentData[index] = currentData;
}
The lists are because I want it to work with multiple Ports from where I can get commands.
SerialPort.DataReceived is invoked on secondary thread.
Read here:
https://msdn.microsoft.com/fi-fi/library/system.io.ports.serialport.datareceived(v=vs.110).aspx
So if you have many SerialPort instances listening, it may happen that there will be more that one Port_DataReceived methods running at the same time. But do not be afraid of local variables, as they live only in specific method call. Therefore 3 different threads running the same method will initiate 3 different local variables, even if their name is the same. But be careful with global variables.
Since Port_DataReceived is synchronous, the next event invocation on the same SerialPort object will wait so these invocations are performed one by one.
So, if you suspect that your producer might run faster than your consumer, you should decouple the two through the use of a queue.
All your producer has to do is push the data it receives into a (thread-safe) queue... a quick operation that will not overrun.
All the consumer has to do is read from the queue, at it's own speed.
TPL Dataflow offers the BufferBlock<T> class which might serve as a handy queue for such a producer/consumer relationship.
You might choose to dig a bit deeper into dataflow. It's perfect for producer/consumer stuff in an async world.
Start here: https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-write-messages-to-and-read-messages-from-a-dataflow-block

How to call Same event Handler with multiple class object in Windows form C# [duplicate]

I have a windows forms application
on which I need to use a for loop having a large number of Remote Calls around 2000 - 3000 calls,
and while executing the for loop, I loose my control on form and form controls, as it becomes a large process and some time it shows "Not Responding" but if I wait for a long it comes back again, I think I need to use some threading model for that, is there any idea, how can I proceed to solve the issue?
You need to perform the long running operation on a background thread.
There are several ways of doing this.
You can queue the method call for execution on a thread pool thread (See here):
ThreadPool.QueueUserWorkItem(new WaitCallback(YourMethod));
In .NET 4.0 you can use the TaskFactory:
Task.Factory.StartNew(() => YourMethod());
And in .NET 4.5 and later, you can (and should, rather than TaskFactory.StartNew()) use Task.Run():
Task.Run(() => YourMethod());
You could use a BackgroundWorker for more control over the method if you need things like progress updates or notification when it is finished. Drag the a BackgroundWorker control onto your form and attach your method to the dowork event. Then just start the worker when you want to run your method. You can of course create the BackgroundWorker manually from code, just remember that it needs disposing of when you are finished.
Create a totally new thread for your work to happen on. This is the most complex and isn't necessary unless you need really fine grained control over the thread. See the MSDN page on the Thread class if you want to learn about this.
Remember that with anything threaded, you cannot update the GUI, or change any GUI controls from a background thread. If you want to do anything on the GUI you have to use Invoke (and InvokeRequired) to trigger the method back on the GUI thread. See here.
private voidForm_Load(object sender, EventArgs e)
{
MethodInvoker mk = delegate
{
//your job
};
mk.BeginInvoke(callbackfunction, null);
}
private void callbackfunction(IAsyncResult res)
{
// it will be called when your job finishes.
}
use MethodInvoker is the easiest way.
Obviously, you need to use background threads. I suggest you read this free e-book.

What happens if a new Entry is written to the Event Log while the application is inside the handler for a previous entry being written?

My application needs to review all new application Event Log entries as they come in.
private void eventLog_Application_EntryWritten(object sender, EntryWrittenEventArgs e)
{
// Process e.Entry
}
What I would like to know is what happens if another Entry is written to the EventLog while a previous Entry is being handled?
The documentation for EventLog.EntryWritten Event provides an example of handling an entry written event which uses threading (which is why I am asking the question).
In this example they use System.Threading and call the WaitOne() and Set() methods on the AutoResetEvent class, however I'm not sure precisely what this code is intended to achieve.
The documentation states that - WaitOne() "blocks the current thread until the current WaitHandle receives a signal", and that Set() "sets the state of the event to signaled, allowing one or more waiting threads to proceed". I'm not sure what the threading portion of this example is intended to demonstrate, and how this relates to how (or if) it needs to be applied in practice.
It appears that WaitOne() blocks the thread immediately after the entry has been written, until it has been handled, where it is then set to signalled (using Set()), before allowing the thread to proceed. Is this the one and only thread for the application?
Most importantly, when my application is not responsible for writing the the events which need to be read from the EventLog, how should this principle be applied? (If, indeed, it needs to be applied.)
What does happen if a new Entry is written while the application is inside the handler?
Nothing dramatic happens, it is serialized by the framework. The underlying winapi function that triggers the EventWritten event is NotifyChangeEventLog(). The .NET Framework uses the threadpool to watch for the event to get signaled with ThreadPool.RegisterWaitForSingleObject(). You can see it being used here.
Which is your cue to why the MSDN sample uses ARE (AutoResetEvent). The event handler runs on that threadpool thread, exactly when that happens is unpredictable. The sample uses a console mode app, without that ARE it would immediately terminate. With the ARE, it displays one notification and quits. Not actually that useful of course, I would personally just have used Console.ReadLine() in the sample so it just keeps running and continues to display info until you press the Enter key.
You don't need this if you use a service or a GUI app, something that's going to run for a long time until the user explicitly closes it. Note the EventLog.SynchronizingObject property, makes it easy to not have to deal with the threadpool thread in a Winforms app.
The example is not really helping to explain the way the AutoResetEvent works in a multi-threaded scenario, so I'll try to explain how I understand it to work.
The AutoResetEvent signal static variable, is instantiated as a new AutoResetEvent with its signaled state set to false, or "non-signaled", meaning that calling signal.WaitOne() will cause the thread that called WaitOne to wait at that point, until the signal variable is "set" by calling the signal.Set() method.
I found an explanation of AutoResetEvent that describes it very well in understandable real-world terms, which also included this excellent example below.
http://www.albahari.com/threading/part2.aspx#_AutoResetEvent
AutoResetEvent
An AutoResetEvent is like a ticket turnstile: inserting a ticket lets
exactly one person through. The “auto” in the class’s name refers to
the fact that an open turnstile automatically closes or “resets” after
someone steps through. A thread waits, or blocks, at the turnstile by
calling WaitOne (wait at this “one” turnstile until it opens), and a
ticket is inserted by calling the Set method. If a number of threads
call WaitOne, a queue builds up behind the turnstile. (As with locks,
the fairness of the queue can sometimes be violated due to nuances in
the operating system). A ticket can come from any thread; in other
words, any (unblocked) thread with access to the AutoResetEvent object
can call Set on it to release one blocked thread.
class BasicWaitHandle
{
static EventWaitHandle _waitHandle = new AutoResetEvent (false);
static void Main()
{
new Thread (Waiter).Start();
Thread.Sleep (1000); // Pause for a second...
_waitHandle.Set(); // Wake up the Waiter.
}
static void Waiter()
{
Console.WriteLine ("Waiting...");
_waitHandle.WaitOne(); // Wait for notification
Console.WriteLine ("Notified");
}
}
According to https://msdn.microsoft.com/en-us/library/0680sfkd.aspx the eventlog components are not thread-safe and that code is there to prevent unexpected behaviour in simultaneous interactions.
If multiple threads are executing these lines simultaneously, if is possible for one thread to change the EventLog.Source Property of the event log, and for another thread to write a message, after that property had been changed.

Blocking calls but do not block thread

Recently I came across a proprietary third-party library and there is a method behave in this way:
public Point ClickOnDrawMat(DrawMat drwmat)
{
Point pt;
//waiting user mouse click on DrawMat and assign to pt
return pt;
}
When my code calling this method from main thread, it will block on this method until user clicks, then get the point return from ClickOnDrawMat.
public void button1_Click(object sender, EventArgs e)
{
Point userClickedPoint = ClickOnDrawMat(oDrwMat); //Wait until user clicked
//Do stuff with point we got
}
However, it doesn't block the main thread. I still can press other button/UI control while it is still waiting for user click.
I noticed that upon waiting for user click, one of the CPU core usage seems pretty high (~75%).
And this is an example of the call stack after I click on another button while it still waiting for user click:
myProgram.frmMain.button2_Click(xxx) Line 23
[External Code]
ThirdPartyLib.ClickOnDrawMat(xxx) Line 16
myProgram.frmMain.button1_Click(xxx) Line 14
I am wondering how can this be done?
Thanks in advance!
We can't tell you exactly how it is done unless somone had a copy of the library and they use a decomplier to see what the code is doing (if you want to do it yourself dotPeek is free and easy to use).
However by how you describe its behavior it is likely repeatedly calling Application.DoEvents() inside the function, this will let other messages be processed while the long running process is doing it's thing.
This is almost never a good coding practice for polling operations due to its high CPU cost, as you noticed, I recommend not doing it in your own code.
The "correct" way to handle this is use one of the Asynchronous Programming Patterns: the async/await feature added in .NET 4.5 or as a NuGet package for 4.0 (TAP), have the library raise an event of its own (EAP), or have the function use a callback function when it is finished (APM). Inside the function itself it should use a event driven system internally so that it does not use CPU power while it is waiting for an event to happen instead of polling.

How to ensure order of async operation calls?

[This appears to be a loooong question but I have tried to make it as clear as possible. Please have patience and help me...]
I have written a test class which supports an Async operation. That operation does nothing but reports 4 numbers:
class AsyncDemoUsingAsyncOperations
{
AsyncOperation asyncOp;
bool isBusy;
void NotifyStarted () {
isBusy = true;
Started (this, new EventArgs ());
}
void NotifyStopped () {
isBusy = false;
Stopped (this, new EventArgs ());
}
public void Start () {
if (isBusy)
throw new InvalidOperationException ("Already working you moron...");
asyncOp = AsyncOperationManager.CreateOperation (null);
ThreadPool.QueueUserWorkItem (new WaitCallback (StartOperation));
}
public event EventHandler Started = delegate { };
public event EventHandler Stopped = delegate { };
public event EventHandler<NewNumberEventArgs> NewNumber = delegate { };
private void StartOperation (object state) {
asyncOp.Post (args => NotifyStarted (), null);
for (int i = 1; i < 5; i++)
asyncOp.Post (args => NewNumber (this, args as NewNumberEventArgs), new NewNumberEventArgs (i));
asyncOp.Post (args => NotifyStopped (), null);
}
}
class NewNumberEventArgs: EventArgs
{
public int Num { get; private set; }
public NewNumberEventArgs (int num) {
Num = num;
}
}
Then I wrote 2 test programs; one as console app and another as windows form app. Windows form app works as expected when I call Start repeatedly:
But console app has hard time ensuring the order:
Since I am working on class library, I have to ensure that my library works correctly in all app models (Haven't tested in ASP.NET app yet). So I have following questions:
I have tested enough times and it appears to be working but is it OK to assume above code will always work in windows form app?
Whats the reason it (order) doesn't work correctly in console app? How can I fix it?
Not much experienced with ASP.NET. Will the order work in ASP.NET app?
[EDIT: Test stubs can be seen here if that helps.]
Unless I am missing something then given the code above I believe there is no way of guaranteeing the order of execution. I have never used the AsyncOperation and AsyncOperationManager class but I looked in reflector and as could be assumed AsyncOperation.Post uses the thread pool to execute the given code asynchronously.
This means that in the example you have provided 4 tasks will be queued to the thread pool synchronously in very quick succession. The thread pool will then dequeue the tasks in FIFO order (first in first out) but it's entirely possible for one of later threads to be scheduled before an earlier one or one of the later threads to complete before an earlier thread has completed its work.
Therefore given what you have there is no way to control the order in the way you desire. There are ways to do this, a good place to look is this article on MSDN.
http://msdn.microsoft.com/en-us/magazine/dd419664.aspx
I use a Queue you can then Enqueue stuff and Dequeue stuff in the correct order. This solved this problem for me.
The documentation for AsyncOperation.Post states:
Console applications do not synchronize the execution of Post calls. This can cause ProgressChanged events to be raised out of order. If you wish to have serialized execution of Post calls, implement and install a System.Threading.SynchronizationContext class.
I think this is the exact behavior you’re seeing. Basically, if the code that wants to subscribe to notifications from your asynchronous event wants to receive the updates in order, it must ensure that there is a synchronization context installed and that your AsyncOperationManager.CreateOperation() call is run inside of that context. If the code consuming the asynchronous events doesn’t care about receiving them in the correct order, it simply needs to avoid installing a synchronization context which will result in the “default” context being used (which just queues calls directly to the threadpool which may execute them in any order it wants to).
In the GUI version of your application, if you call your API from a UI thread, you will automatically have a synchronization context. This context is wired up to use the UI’s message queueing system which guarantees that posted messages are processed in order and serially (i.e., not concurrently).
In a Console application, unless if you manually install your own synchronization context, you will be using the default, non-synchronizing threadpool version. I am not exactly sure, but I don’t think that .net makes installing a serializing synchronization context very easy to do. I just use Nito.AsyncEx.AsyncContext from the Nito.AsyncEx nuget package to do that for me. Basically, if you call Nito.AsyncEx.AsyncContext.Run(MyMethod), it will capture the current thread and run an event loop with MyMethod as the first “handler” in that event loop. If MyMethod calls something that creates an AsyncOperation, that operation increments an “ongoing operations” counter and that loop will continue until the operation is completed via AsyncOperation.PostOperationCompleted or AsyncOperation.OperationCompleted. Just like the synchronization context provided by a UI thread, AsyncContext will queue posts from AsyncOperation.Post() in the order it receives them and run them serially in its event loop.
Here is an example of how to use AsyncContext with your demo asynchronous operation:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting SynchronizationContext");
Nito.AsyncEx.AsyncContext.Run(Run);
Console.WriteLine("SynchronizationContext finished");
}
// This method is run like it is a UI callback. I.e., it has a
// single-threaded event-loop-based synchronization context which
// processes asynchronous callbacks.
static Task Run()
{
var remainingTasks = new Queue<Action>();
Action startNextTask = () =>
{
if (remainingTasks.Any())
remainingTasks.Dequeue()();
};
foreach (var i in Enumerable.Range(0, 4))
{
remainingTasks.Enqueue(
() =>
{
var demoOperation = new AsyncDemoUsingAsyncOperations();
demoOperation.Started += (sender, e) => Console.WriteLine("Started");
demoOperation.NewNumber += (sender, e) => Console.WriteLine($"Received number {e.Num}");
demoOperation.Stopped += (sender, e) =>
{
// The AsyncDemoUsingAsyncOperation has a bug where it fails to call
// AsyncOperation.OperationCompleted(). Do that for it. If we don’t,
// the AsyncContext will never exit because there are outstanding unfinished
// asynchronous operations.
((AsyncOperation)typeof(AsyncDemoUsingAsyncOperations).GetField("asyncOp", BindingFlags.NonPublic|BindingFlags.Instance).GetValue(demoOperation)).OperationCompleted();
Console.WriteLine("Stopped");
// Start the next task.
startNextTask();
};
demoOperation.Start();
});
}
// Start the first one.
startNextTask();
// AsyncContext requires us to return a Task because that is its
// normal use case.
return Nito.AsyncEx.TaskConstants.Completed;
}
}
With output:
Starting SynchronizationContext
Started
Received number 1
Received number 2
Received number 3
Received number 4
Stopped
Started
Received number 1
Received number 2
Received number 3
Received number 4
Stopped
Started
Received number 1
Received number 2
Received number 3
Received number 4
Stopped
Started
Received number 1
Received number 2
Received number 3
Received number 4
Stopped
SynchronizationContext finished
Note that in my example code I work around a bug in AsyncDemoUsingAsyncOperations which you should probably fix: when your operation stops, you never call AsyncOperation.OperationCompleted or AsyncOperation.PostOperationCompleted. This causes AsyncContext.Run() to hang forever because it is waiting for the outstanding operations to complete. You should make sure that your asynchronous operations complete—even in error cases. Otherwise you might run into similar issues elsewhere.
Also, my demo code, to imitate the output you showed in the winforms and console example, waits for each operation to finish before starting the next one. That kind of defeats the point of asynchronous coding. You can probably tell that my code could be greatly simplified by starting all four tasks at once. Each individual task would receive its callbacks in the correct order, but they would all make progress concurrently.
Recommendation
Because of how AsyncOperation seems to work and how it is intended to be used, it is the responsibility of the caller of an asynchronous API that uses this pattern to decide if it wants to receive events in order or not. If you are going to use AsyncOperation, you should document that the asynchronous events will only be received in order by the caller if the caller has a synchronization context that enforces serialization and suggest that the caller call your API on either a UI thread or in something like AsyncContext.Run(). If you try to use synchronization primitives and whatnot inside of the delegate you call with AsyncOperation.Post(), you could end up putting threadpool threads in a sleeping state which is a bad thing when considering performance and is completely redundant/wasteful when the caller of your API has properly set up a synchronization context already. This also enables the caller to decide that, if it is fine with receiving things out of order, that it is willing to process events concurrently and out of order. That may even enable speedup depending on what you’re doing. Or you might even decide to put something like a sequence number in your NewNumberEventArgs in case the caller wants both concurrency and still needs to be able to assemble the events into order at some point.

Categories

Resources