Reputation: 11458
I have a following fairly simple scenario: Some data needs to be written into a DB (pretty big collection) that can be partitioned. But I have two problems:
Easy one: would like to have an option to print the progress bar, so that would like to know how many records have been inserted so far from time to time (kinda shared counter among the threads).
Harder one: each record needs to be accompanied by a timestamp. The timestamps have a starting time and an interval. The timestamp is unfortunately not a part of the record but in sequential programming can be simply calculating by incrementing the current one by a particular interval.
So far, the question is: how to implement the above constraints properly? Is it somehow possible to separate the loop body from the code that is executing when promoting an iteration (++i
or newTimeStamp = oldTimeStamp.AddSeconds(...)
, so that that kind of code will be always executed on a single thread, contrary to the loop body that will be parallelized? If possible, the code snippet will be very helpful, though I'll be happy to get even any pointers/names/keywords. Thanks.
Upvotes: 0
Views: 1714
Reputation: 700860
You don't need to do that in a single thread, you just have to make sure that only one thread at a time does it:
public class Synchoniser {
private int _progress;
private int _total;
private int _counter;
pricate object _sync;
public Synchroniser(int total, int counterSeed) {
_progress = 0;
_total = total;
_counter = counterSeed;
_sync = new Object();
}
public void AdvanceProgress() {
lock (_sync) {
_progress++;
}
}
public int GetProgress() {
lock (_sync) {
return 100 * _progress / _total;
}
}
public int GetNextCounter() {
lock (_sync) {
_counter++;
return _counter;
}
}
}
Create a single instance of the class, and give it to each thread. Now they can each advance the progress and get the next counter value.
Upvotes: 0
Reputation: 35594
For the part 1, you can use either a mutex (lock
statement), or even just one of Interlocked
methods.
int counter = 0;
object counterLock = new object();
void IncreaseCounter()
{
lock (counterLock)
counter++;
}
int GetCounter()
{
lock (counterLock)
return counter;
}
or
int counter = 0;
void IncreaseCounter()
{
Interlocked.Increment(ref counter);
}
int GetCounter()
{
return Interlocked.Read(ref counter);
}
For using from GUI, you can propagate your counter changes to an appropriate DependencyProperty (if you are using WPF).
For the second part, why cannot the timestamp be calculated for each record individually, so that you don't need to share anything between threads? Maybe I did't understand your question properly, could you please describe the problem #2 in more detail?
Upvotes: 1