I have a use case where I need to log data to file Asynchronously which I do not see it possible with Microsoft.Extensions.Logging so need your help to figure out the best solution
Use Seri ILogger interface, which according to this github doc does not seem to be using async await implementation but rather uses a background worker thread.
The wrapped sink (File in this case) will be invoked on a worker thread while your application's thread gets on with more important stuff.
Write My Custom Logger which utilizes TextWriter.Synchronized and WriteLineAsync
OR if there is any other solution which I am not aware of
It's normal for logging to use a background thread so it can expose a synchronous logging API. If all logging APIs were asynchronous, then that would force practically every method to be asynchronous.
Logging synchronously to a background thread also enables buffering and batched writes, which increase performance.
Related
Is there a way to be notified (e.g. via an event or a callback) whenever a new ThreadPool thread is created?
I'm working on a .net console app that is using pjlib library via P/Invoke. This library requires that every thread that uses any of its APIs has to be previously registered via pj_thread_register API:
Register a thread that was created by external or native API to PJLIB. This function must be called in the context of the thread being registered. When the thread is created by external function or API call, it must be 'registered' to PJLIB using pj_thread_register(), so that it can cooperate with PJLIB's framework. During registration, some data needs to be maintained, and this data must remain available during the thread's lifetime.
When trying to call any pjlib function form an unregistered thread the library will indeed assert with the message:
Calling pjlib from unknown/external thread. You must
register external threads with pj_thread_register()
before calling any pjlib functions.
Now, the application's business logic uses async and await, and being it a console app the SynchronizationContext is null, meaning all continuations will run on ThreadPool's threads, including the P/Invokes calls to pjsip APIs, making necessary to call pj_thread_register() before every call to any of the pjsip APIs, to be sure that a newly created ThreadPool's thread won't try to use any pjsip API before registering itself.
I thought that if I could be notified (with a callback that gets called in the context of the newly created thread) whenever a new threadpool thread is created I could use this callback to register the new thread only once.
Is there a way to receive such a notification?
Alternatively I could use a SynchronizationContext (e.g. Stephen Cleary's AsyncContext or Stephen Toub's AsyncPump) on the main or on some dedicated threads (and register them as soon as I create them), but this would mean to redesign the application, maybe going towards an actor model, is there an alternative approach to face this kind of situations?
It might be possible to use profiling APIs or ETW to detect all thread pool creation events. I'm not sure how easy it would be to execute code in the context of that thread as a result of those events, though.
I would recommend using a [ThreadStatic] static bool PjInitialized; field in your interop layer, and add a check to every call at that layer. If it's not initialized, then call pj_thread_register before the actual call.
I need to use a third-party DLL which implements a TCP socket client (in C++) using blocking calls. So basically (pseudocode);
void DoRequest()
{
send(myblockingSocket,data);
recv(myblockingSocket,responsedata);
}
What is the recommended way to make these calls accessible in .NET as asynchronous calls using async-await (without changing the original DLL) ?
I read: https://learn.microsoft.com/en-us/dotnet/standard/async-in-depth#deeper-dive-into-tasks-for-an-io-bound-operation and https://learn.microsoft.com/en-us/dotnet/csharp/async and several other pages and did not find another solution than spawning a new task, which is not recommended to do on I/O bound operations because of the task creation overhead.
What is the recommended way to make these calls accessible in .NET as asynchronous calls using async-await (without changing the original DLL) ?
There is no recommended solution because this isn't possible. Either the DLL itself must be changed/replaced so that it supports asynchrony, or the asynchronous calls will just be running the synchronous code on a background thread - what I call "fake asynchrony" because it appears asynchronous but is actually taking up a thread anyway.
... did not find another solution than spawning a new task, which is not recommended to do on I/O bound operations because of the task creation overhead.
It's actually not recommended for a couple of reasons:
It lies to the upstream code. It says "this API is asynchronous" when it's not. This can lead consumers to make incorrect decisions, e.g., preferring the asynchronous API in a server scenario.
It doesn't provide any actual benefit. Implementing a method with Task.Run forces the consumers to use an additional thread. If you just kept the API synchronous, then consumers can choose to call it with Task.Run or not, depending on their needs.
Here is my scenario:
We have a library which has a "MethodA" in a class which makes a http call using C# HttpClient and retrieves all notification which are in the queue. We are using .NET Core 3.1. I want to add another class in the same library which will call this "MethodA" on a scheduled interval. I have used Task.Run and Task.Delay to achieve this in my test app and it works. Only thing is this is an I/O bound call and not CPU bound operation and it is recommended by Stephen Cleary to avoid using Task.Run on I/O bound calls here.
How can I achieve this?
Thanks,
Sal
I/O bound calls are already handled by your operating system in an event driven way. Windows for example does it with overlapped file calls.
So the answer to your question is, don't use the thread pool, await on the OS call with Stream.ReadAsync and friends.
Edit: I just noticed you're talking about HttpClient, and the same answer applies there. Get the response stream and use async read calls on it instead of tying up your thread pool for no reason.
I've been reading about the new async and await operators in C# and tried to figure out in which circumstances they would possibly be useful to me. I studied several MSDN articles and here's what I read between the lines:
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
async void button1_Click(object sender, EventArgs e)
{
// even though this call takes a while, the UI thread will not block
// while it is executing, therefore allowing further event handlers to
// be invoked.
await SomeLengthyOperationAsync();
}
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
In other words, if you create a thread with an ordinary good old ThreadStart entry point (or a Console application with good old static int Main(string[] args)), then you cannot use async and await because at one point you would have to use await, and make the method that uses it async, and hence in the calling method you also have to use await and make that one async and so on. But once you reach the thread entry point (or Main()), there's no caller to which an await would yield control to.
So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop. I guess all that makes indeed sense, since MSDN states that async programming does not mean multithreading, but using the UI thread's spare time instead; when using a console application or a thread with a user defined entry point, multithreading would be necessary to perform asynchronous operations (if not using a compatible message loop).
My question is, are these assumptions accurate?
So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop.
That's absolutely not the case.
In Windows Forms and WPF, async/await has the handy property of coming back to the UI thread when the asynchronous operation you were awaiting has completed, but that doesn't mean that's the only purpose to it.
If an asynchronous method executes on a thread-pool thread - e.g. in a web service - then the continuation (the rest of the asynchronous method) will simply execute in any thread-pool thread, with the context (security etc) preserved appropriately. This is still really useful for keeping the number of threads down.
For example, suppose you have a high traffic web service which mostly proxies requests to other web services. It spends most of its time waiting for other things, whether that's due to network traffic or genuine time at another service (e.g. a datbase). You shouldn't need lots of threads for that - but with blocking calls, you naturally end up with a thread per request. With async/await, you'd end up with very few threads, because very few requests would actually need any work performed for them at any one point in time, even if there were a lot of requests "in flight".
The trouble is that async/await is most easily demonstrated with UI code, because everyone knows the pain of either using background threads properly or doing too much work in the UI thread. That doesn't mean it's the only place the feature is useful though - far from it.
Various server-side technologies (MVC and WCF for example) already have support for asynchronous methods, and I'd expect others to follow suit.
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
Not true - methods marked async just mean they can use await, but callers of those methods have no restrictions. If the method returns Task or Task<T> then they can use ContinueWith or anything else you could do with tasks in 4.0
A good non-UI example is MVC4 AsyncController.
Ultimately, async/await is mostly about getting the compiler rewriting so you can write what looks like synchronous code and avoid all the callbacks like you had to do before async/await was added. It also helps with the SynchronizationContext handling, useful for scenarios with thread affinity (UI frameworks, ASP.NET), but even without those, it's still useful. Main can always do DoStuffAsync().Wait(); for instance. :)
My question is, are these assumptions accurate?
No.
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
True. Also true for other UI applications including Silverlight and Windows Store.
And also true for ASP.NET. In this case, it's the HTTP request thread that is not blocked.
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
This is a best practice ("async all the way down"), but it's not strictly required. You can block on the result of an asynchronous operation; many people choose to do this in Console applications.
an ordinary good old ThreadStart entry point
Well... I do have to take issue with "ordinary good old". As I explain on my blog, Thread is pretty much the worst option you have for doing background operations.
I recommend you review my introduction to async and await, and follow up with the async / await FAQ.
async-await is only wrapper for Task class manipulations, which is part of so named Tasks Parallel Library - TPL(published before async-await auto code generation tech.)
So fact is you may not use any references to UI controls within async - await.
Typically async-await is powerfull tool for any web and server relations, loading resources, sql. It works with smart waiting data with alive UI.
Typically TPL application: from simple big size loop till multi stages parallel calculations in complex calculations based on shared data (ContinueWith and so on)
I have a situation where I have a polling thread for a TCPClient (is that the best plan for a discrete TCP device?) which aggregates messages and occasionally responds to those messages by firing off events. The event producer really doesn't care much if the thread is blocked for a long time, but the consumer's design is such that I'd prefer to have it invoke the handlers on a single worker thread that I've got for handling a state machine.
The question then is this. How should I best manage the creation, configuration (thread name, is background, etc.) lifetime, and marshaling of calls for these threads using the Task library? I'm somewhat familiar with doing this explicitly using the Thread type, but when at all possible my company prefers to do what we can just through the use of Task.
Edit: I believe what I need here will be based around a SynchronizationContext on the consumer's type that ensures that tasks are schedules on a single thread tied to that context.
The question then is this. How should I best manage the creation, configuration (thread name, is background, etc.) lifetime, and marshaling of calls for these threads using the Task library?
This sounds like a perfect use case for BlockingCollection<T>. This class is designed specifically for producer/consumer scenarios, and allows you to have any threads add to the collection (which acts like a thread safe queue), and one (or more) thread or task call blockingCollection.GetConsumingEnumerable() to "consume" the items.
You could consider using TPL DataFlow where you setup an ActionBlock<T> that you push messages into from your TCP thread and then TPL DataFlow will take care of the rest by scaling out the processing of the actions as much your hardware can handle. You can also control exactly how much processing of the actions happen by configuring the ActionBlock<T> with a MaxDegreeOfParallelism.
Since processing sometimes can't keep up with the flow of incoming data, you might want to consider "linking" a BufferBlock<T> in front of the ActionBlock<T> to ensure that the TCP processing thread doesn't get too far ahead of what you can actually process. This would have the same effect as using BlockingCollection<T> with a bounded capacity.
Finally, note that I'm linking to .NET 4.5 documentation because it's easiest, but TPL DataFlow is available for .NET 4.0 via a separate download. Unfortunately they never made a NuGet package out of it.