Preferred way of passing data across threads - c#

I have a main thread which should process data coming from several worker threads.
But this data is not a specific class.
There are around 6-7 classes, and I need to pass one of this class to the main thread from worker threads.
Previously I had only one class which was passed across threads. I was using;
BlockingCollection<MyClass> mainQueu = new BlockingCollection<MyClass>(new ConcurrentQueue<MyClass>());
So I was pushing MyClass instances from several threads to mainQueu and main thread was trying to take from the mainQueu.
But what if I have more than one classes. Which way is better?
Having a queue for each type of class:
Of course there should be another queue of type maybe enum, specifying which class is pushed to the queue. And main thread always tries to take from this queue. As soon as any item comes, it will takes from related queue.
Casting:
Having only one main queue, and in mainQueue class, I can have object member.
And enum which specifies type of object member.
And I can convert class to object when pushing to queue, and than in main thread I can cast it back to original class.
Hope it is clear.
Many thanks,regards

A useful trick here is to just have the worker as a queue of delegates; for example, Action. Then the caller can enqueue the appropriate method and (via captured varialbes) any necessary state.
Say, for example, you have a void Enqueue(Action) method; the caller could do:
queue.Enqueue(targetObject.Method);
(where targetObject.Method is a void Method() {...}), or can do something like:
queue.Enqueue(() => SomeMethod(foo, bar, 123));
(where foo and bar are local to the code that wants the work done)
so we've passed lots of state at once, and not once had to think about types - just operations.

Related

What type of queue to use?

I have a static class called Monitor that includes a method LogToMonitor.
public static void LogToMonitor(MonitorDevice device, MonitorCategory category, MonitorType type, string msg)
It creates a MonitorEntry type and updates a property which does a property change to the UI and adds to an ObservableCollection.
public ObservableCollection<MonitorEntry> MonitorEntries { get; }
I now have another thread that needs to LogToMonitor. This is going to cause issues having multiple calling threads. I'm thinking I should have a Producer Consumer approach.
What type of collection should I use?
Should the Queue be a separate class which processes the calls and updates the UI?
Can I have multiple threads still call LogToMonitor method which puts them in the Queue?
BlockingCollection<T> is what you are looking for probably. It's an implementation of the Producer-Consumer pattern. https://learn.microsoft.com/en-us/dotnet/standard/collections/thread-safe/blockingcollection-overview
ObservableCollection is not thread-safe so you can run into exceptions. Check the post of Robert Fraser, he has posted the code for a thread safe ObservableCollection. Use this instead of the standard implementation and should not have problems with multiple threads. How to make ObservableCollection thread-safe?

Pass an object to a new thread inside a loop [duplicate]

I have an object that contains a very large 3D-array of doubles and I need to start a new thread that need the data of this array, so I will either need to start a new thread passing the object (which contains a whole lot of other data too) to the new thread or I just pass the 3D-array to the new thread.
For the first solution I would simply do the following:
MyClass
{
...
public double[,,] _data = new double[x,y,z];
...
}
MyMethod(object MyObject)
{
//do stuff with (MyObject as MyClass)
}
MyClass _newObject = new MyClass();
Thread thread = new Thread(new ParameterizedThreadStart(MyMethod));
thread.Start(_newObject);
My question now: As I pass the object _newObject to the new thread, is that object sent to the thread by reference or is the object copied and the copy used by the new thread? The problem is that the object contains data of around 300MB and it would be almost impossible if copies are used since I need to start around 10 threads that need to use data of that object.
By reference.
If you change the data in your thread it will change the original data you put in. Same applies if you change the data outside the thread your thread will see the modified data.
You need proper locking mechanisms so that it will not collide when accessing the data from multiple threads.
10 thread ? how do you plan to maintain the data integrity of the _newObject ?
Saying that copies will not be passed, only the reference will be used.
If you going to call the method MyMethod(object MyObject) in 10 different threads
will the MyObject be different objects ?? if not you are better off refractoring the method.
Also you should remember that a thread is just a liner set of instructions to be executed.
So just because of using multiple threads your object size will not increase in the memory.
the very advantage of multi threading is to make use of different threads to process your instructions, and does not make copies of objects.
Assuming that your MyClass is a class, then the reference of the object is only passed to the new thread, since it is a reference type(read more on reference types on MSDN), i would also suggest that you use a lock in order avoid deadlock issues you can do that simply by using the lock keyword
To be more precise it's send by reference copy.
Since this is a reference type, only a reference is copied in this case, and not all data.
That's why you have to care about locking mechanisms in cases where more then one thread accesses the data this object refers to.

Returning status from a worker class

I have a service class and a worker class. The worker class does all the processing.
class WorkerClass
{
public void ProcessWork(<params to the method>)
{
// Get the tasks from the DB.
// Call a 3rd party web service to process each of the tasks.
}
}
In my service class, I instantiate the worker class and call the method. The question is, how do I get the number of tasks processed in the service class?
I have thought of 3 options:
Expose an event from the worker class. Hook up an event handler in the service class.
Modify the signature of ProcessWork method so that it accepts a delegate:
public void ProcessWork(object obj1, Action<int, int> actionProgressTracker)
Expose a property from the worker class and get the property in the service class. Refresh the property every 30 seconds.
What would be a clean way of getting the status?
The first two options are really functionally identical. Both can work just fine for what you need to do. The second has an implication that the delegate is required, whereas the first implies that it is not. An event might also imply that it is used beyond the scope of just this one method.
As for the third option, it doesn't give the caller the opportunity to execute code when the number updates, it just gives them the opportunity to access the information.
So if the caller of this type is going to need to do something with this information *every time the value changes) then you should be using something comparable to one of the first two options so that the worker can "push" information to the caller.
If the caller wants to "pull" the information from the worker whenever it wants the information, then go with the third option.
Note that there is also a Progress class that you can use, with a corresponding IProgress interface, that's comparable to your first two options, but is specifically tailored for a worker updating a UI with progress.
Both push and pull methods can actually be sensible for updating a UI with progress of a backround task. If progress occurs infrequently it may make sense to update the UI every time progress changes, so the UI will want to be "notified" of when those updates happen. If the updates are very frequent, then the UI may want to instead have a timer and pull the current status every so often, to avoid taxing the UI with more updates than are needed or than it can handle.
Of course, if you're pushing information and not just something like a percent complete, then it may be important to not lose any of that information, in which case your 3rd approach isn't an option, as multiple updates may happen in between fetches.
And of course if you're writing a sufficiently generalized worker, you may want to expose both a push and pull mechanism, to let the caller choose the appropriate one.

Creating multiple threads for same method on an instance on an object

I have a question. Is it possible and valid, if I have an object with a method DoSomething(), if I create multiple threads for this method, will it work and would it run as a seperate thread of its own?
E.g.
public class SomeClass
{
public void DoSomething()
{
//somethings done here
}
}
public class MainProgram
{
public MainProgram()
{
InitializeComponents();
}
protected override OnStart(string[] args)
{
SomeClass sc = new SomeClass();
Thread workerOne = new Thread(() => sc.DoSomething());
workerOne.Start();
Thread workerTwo = new Thread(() => sc.DoSomething());
workerTwo.Start(); //start a new thread calling same method
}
}
I hope that kind of explains what I mean. Would this work or cause any problems?
I am writing a program that needs to almost be realtime software, I am currently deciding whether initialising a new instance of SomeClass is better or not?
Hope someone can answer. If my question's dont make sense, please comment and I'll explain further!
Thanks,
Base33
PS The code was written specifically for the example :)
Each thread has a separate call stack, so yes they can both be using the same method on the same object. And indeed, if needed each thread can (via recursion) call the same method on the same instance multiple times if you really want.
However, what might trip you up is if you are using state in that object (instance or static fields, etc, and anything related from that state). You will need to ensure your access to any shared state gives full consideration (and presumably synchronisation) to multi-threaded access.
Yes you can do that. You will however have to make sure that your member accesses within that method are thread safe.
If you mutate the state of the object you should either lock your reads and writes (not speaking of any particular mechanism) or verify that it's harmless to interupt the method at any given time and that the other call on a different thread will still work correctly
Is it possible and valid, if I have an object with a method DoSomething(), if I create multiple threads for this method, will it work and would it run as a seperate thread of its own?
Yes it is possible. In your code example, DoSomething is being called on the same instance of SomeClass. Both threads share this. You have two distinct threads but one actual object being shared.
Would this work or cause any problems?
That entirely depends on your use case. It may or may not. If objects are shared, you need to synchronize access to them.
It has no problem. I will run without any error.
It is just like creating an object and call method on this object
twice. only fact is that two occurrence of calling same method is on
different thread.

creating and terminating a thread contained in a collection

I have a custom collection (a thread-safe ObservableQueue). I implemented the business logic inside the collection class (i.e. dequeue the items one by one and expose them to the outside). This is working fine. To prevent the collection from blocking the thread it is initialised in, the OnservableQueue implements a thread to perform that work. Now I am not perfectly sure of any pitfalls that could occur.
Is it a bad idea to initialise (not start! only initialise) the thread in the constructor? And what would be a good, if not best, practice of terminating the thread? Note, I dont need to know how to terminate a thread, that is working fine, I am rather interested in weather there is something wrong doing it using the disposable pattern or creating a method which would need to get called to terminate the thread. If implementing IDisposable are there any things I have to take in account regarding the collection/queue?
Edit: The thread is actually only pre-initialised to prevent NullReferenceException from being thrown in the Enqueue Method, where it is properly initilised again (the Enqueue Method is supposed to check weather a dequeuing thread is running already and if not to start a new one). Note that whenever all items are dequeued and the thread has done its work it will not be alive any longer either, so any time the queue is empty and a new item is added a new thread will get started to process the queue:
if (!_dequeuingThread.IsAlive)
{
// start the dequeuing thread
_dequeuingThread = new Thread(new ThreadStart(StartDequeuing));
_dequeuingThread.Name = "DeQueueThread";
_dequeuingThread.Start();
}
The if-statement does need an initialised thread. There are other possible ways of achieving this, but pre-initialising the thread seemed the least bothersome. You see that after checking weather the thread is alive, which it should not when being pre-initialised, it gets initialised again properly.
I don't see anything wrong with initialising in the constructor, but obviously bare in mind they will be initialised in a different thread than your worker thread.
As for stopping, I generally have a volatile boolean flag that the worker checks to keep running. If your worker thread sleeps at all, then have it wait on an event rather than sleeping, so you can wake it up immediately when stopping it.
There seems to be a problem with the fact that the consumer will initialize this collection object by calling its constructor and it would think that the object is initialized (that what the constructor is supposed to do), which is not correct as the initialization is happening on a separate thread created by the constructor. So, basically you need to implement some sort of "Asynchronous API on this object" to initialize this collection such that the consumer calls the initialize method (after creating the object using constructor) and then either by either passing a callback to the initialize method or by registering to an event on the collection object the consumer gets to know that the initialization has been completed.

Categories

Resources