Static Class Stream Security

I want to create my own event system in my Windows application in C #. To do this, I will write the following class:

internal class EventManager { private static List<EventRecord> s_listEvents = new List<EventRecord>(); public static void AddEvent(EventRecord record) { record.EventDate = DateTime.Now; s_listEvents.Add(record); } public static List<EventRecord> GetRecordsByDate(DateTime date) { var r = (from l in s_listEvents where l.EventDate >= date select l).ToList<EventRecord>(); return r; } } 

I want to be sure that the EventManager class is thread safe. Because I'm going to create hundreds of threads at the same time in my application. All threads are likely to use this class to generate events. And the GetRecordsByDate function can be called from outside the class at a time when the AddEvent function will be called from different threads.

Can you just tell me that this design is suitable for multi-threaded Windows applications? If this is not thread safe, then how can I make my class or its members thread safe? Should I use a synchronization object to lock the entire EventManager class, or should I use readwritelocker to lock the static member s_listEvents ?

+4
source share
5 answers

Instead of using List<T> , you should use ConcurrentBag<T> instead.

ConcurrentBag is a realistic package implementation optimized for scenarios where the same stream will produce and consume data stored in the bag.

Additional Information:

http://msdn.microsoft.com/en-us/library/dd381779.aspx

Also, be careful to create the number of threads to access, more than 100 threads will do slow performance, because the switching context takes time.

Edit: for .NET 3.5 you can make it thread safe using a simple lock

 internal class EventManager { private static List<EventRecord> s_listEvents = new List<EventRecord>(); private static object _syncObject = new object(); public static void AddEvent(EventRecord record) { record.EventDate = DateTime.Now; lock(_syncObject) { s_listEvents.Add(record); } } public static List<EventRecord> GetRecordsByDate(DateTime date) { lock (_syncObject) { var r = (from l in s_listEvents where l.EventDate >= date select l).ToList<EventRecord>(); return r; } } } 

Edit :

Depending on the situation, if you read the data very often, use ReaderWriterLockSlim with ReaderWriterLock best for the entire application, because it allows multiple threads to read data.

If not, use a lock that has better overall performance.

See link:

http://blogs.msdn.com/b/pedram/archive/2007/10/07/a-performance-comparison-of-readerwriterlockslim-with-readerwriterlock.aspx

+2
source

Since the class is static, you must block the s_listEvents element. There is likely a high likelihood that subscribers will not have access to the shared lock object, unless you make the lock available as a static member of the EventManager itself (or any other static class). If so, you can also implement locking around access to s_listEvents in the EventManager directly. This way you avoid problems when callers forget to acquire a lock.

For this, a good choice for the reader / writer.

+2
source

You can use the ReaderWriterLock class:

 internal class EventManager { static ReaderWriterLock rwl = new ReaderWriterLock(); private static List<EventRecord> s_listEvents = new List<EventRecord>(); public static void AddEvent(EventRecord record) { record.EventDate = DateTime.Now; rwl.AcquireWriterLock(0); try { s_listEvents.Add(record); } finally { rwl.ReleaseWriterLock(); } } public static List<EventRecord> GetRecordsByDate(DateTime date) { rwl.AcquireReaderLock(0); try { var r = (from l in s_listEvents where l.EventDate >= date select l).ToList<EventRecord>(); return r; } finally { rwl.ReleaseReaderLock(); } } } 
+1
source

The simplest answer to your question is this: For your solution to be thread safe, you must protect the data warehouse from simultaneous access. This is done by locking your list at any time that it accesses. This means that when you iterate over a list, add it or remove from it, you must block this region.

You probably won’t want to create another 100 threads, even if you access this number of servers, you can use the thread pool instead, see http://msdn.microsoft.com/en-us/library/0ka9477y(v=vs .90) .aspx . This will give you a thread pool that will be used for simple validation - data loading - validation tasks, such as you seem to be describing.

When writing multi-threaded applications, it is important to consider the basic storage usage pattern. If your application runs hundreds of supplements per second, you may want to have a read-only copy of your underlying data structure that does not block the entire system every time you try to retrieve records by date. For a detailed introduction, see Intel Optimization Guide

+1
source

Useful link:

How to create a thread safe class

 private object _lock; public static void AddEvent(EventRecord record) { lock (_lock) { record.EventDate = DateTime.Now; s_listEvents.Add(record); } } 
0
source

Source: https://habr.com/ru/post/1437130/


All Articles