I am working on a class library that logs audit details of a web application in several types of datasources(file, xml, database) based on policies defined in the web configuration file.
My Audit log method has a signature similar to this:
public static void LogInfo(User user, Module module, List lst);
Web application uses this method to log important pieces of details like warnings, error and even exception details.
Since in a single workflow, there are more than 700+ calls to these methods , I thought of making them asynchronous. I used simple method from ThreadPool class called QueueUserWorkItem
ThreadPool.QueueUserWorkItem(o => LogInfo(User user, Module module, List<Object> lst) );
but this does not ensure the order in which work item was queued to it. Even though all my information was logged but entire ordering was messed up. In my text file my logs were not in the order in which they were called.
Is there a way I can control the ordering of the threads being called using QueueUserWorkItem?
I don’t think you can specify ordering when using
QueueUserWorkItem.To run the logging in parallel (on some background thread), you could use
ConcurrentQueue<T>. This is a thread-safe collection that can be accessed from multiple threads. You could create one work item (or a thread) that reads elements from the collection and writes them to a file. Your main application would add items to the collection. The fact that you’re adding items to the collection from a single thread should guarantee that they will be read in the right order.To keep things simple, you can store
Actionvalues in the queue:The background task can just take
Actions from the queue and run them:If you need to stop the background processor (that writes data to the log), you can create a
CancellationTokenSourceand also end thewhileloop when the token is being cancelled (by the main thread). This cha be checked usingIsCancellationRequestedproperty (see MSDN)