我有一个相当简单的场景: 有些数据需要写入可以分区的DB(非常大的集合)中。但我有两个问题:
简单的一个:希望有一个打印进度条的选项,这样就可以知道到目前为止已经插入了多少条记录(在线程中有点共享计数器)。
更难一个:每个记录都需要附带一个时间戳。时间戳具有开始时间和间隔。遗憾的是,时间戳不是记录的一部分,但顺序编程可以简单地通过将当前时间增加一个特定的间隔来计算。
到目前为止,问题是:如何正确实施上述约束?是否有可能将循环体与促进迭代时执行的代码(++i
或newTimeStamp = oldTimeStamp.AddSeconds(...)
分开,以便这种代码总是在单个线程上执行,这与将被并行化的循环体?如果可能的话,代码片段将非常有用,尽管我很乐意得到任何指针/名称/关键字。谢谢。
答案 0 :(得分:1)
对于第1部分,您可以使用互斥锁(lock
statement),甚至只使用Interlocked
methods中的一个。
int counter = 0;
object counterLock = new object();
void IncreaseCounter()
{
lock (counterLock)
counter++;
}
int GetCounter()
{
lock (counterLock)
return counter;
}
或
int counter = 0;
void IncreaseCounter()
{
Interlocked.Increment(ref counter);
}
int GetCounter()
{
return Interlocked.Read(ref counter);
}
要从GUI使用,您可以将计数器更改传播到适当的DependencyProperty(如果您使用的是WPF)。
对于第二部分,为什么不能单独为每条记录计算时间戳,这样您就不需要在线程之间共享任何内容?也许我没有理解你的问题,你能不能更详细地描述问题#2?
答案 1 :(得分:0)
您不需要在单个线程中执行此操作,您只需确保一次只有一个线程执行此操作:
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;
}
}
}
创建该类的单个实例,并将其提供给每个线程。现在他们每个人都可以推进进度并获得下一个计数器值。