C# 并行:如何正确同步

C# 并行:如何正确同步,c#,multithreading,parallel-processing,task-parallel-library,C#,Multithreading,Parallel Processing,Task Parallel Library,我有一个相当简单的场景: 有些数据需要写入可以分区的DB(相当大的集合)。但我有两个问题: 简单一点:希望有一个打印进度条的选项,以便知道到目前为止不时插入了多少条记录(类似于线程之间的共享计数器) 更难的是:每条记录都需要有一个时间戳。时间戳具有开始时间和间隔。不幸的是,时间戳不是记录的一部分,但是在顺序编程中,可以通过将当前时间戳增加一个特定的间隔来简单地计算时间戳 到目前为止,问题是:如何正确实施上述约束?在升级迭代时(++i或newTimeStamp=oldTimeStamp.AddSe

我有一个相当简单的场景: 有些数据需要写入可以分区的DB(相当大的集合)。但我有两个问题:

  • 简单一点:希望有一个打印进度条的选项,以便知道到目前为止不时插入了多少条记录(类似于线程之间的共享计数器)

  • 更难的是:每条记录都需要有一个时间戳。时间戳具有开始时间和间隔。不幸的是,时间戳不是记录的一部分,但是在顺序编程中,可以通过将当前时间戳增加一个特定的间隔来简单地计算时间戳


  • 到目前为止,问题是:如何正确实施上述约束?在升级迭代时(
    ++i
    newTimeStamp=oldTimeStamp.AddSeconds(…)是否可能以某种方式将循环体与正在执行的代码分开
    ,这样这种代码将始终在单个线程上执行,而不是并行化的循环体?如果可能的话,代码片段将非常有用,尽管我很乐意获得任何指针/名称/关键字。谢谢。

    对于第1部分,您可以使用互斥锁(),甚至只使用其中一个

    对于从GUI使用,您可以将计数器更改传播到适当的DependencyProperty(如果您使用的是WPF)


    对于第二部分,为什么不能单独计算每条记录的时间戳,这样就不需要在线程之间共享任何内容?也许我没有正确理解您的问题,请您更详细地描述问题#2?

    您不需要在单个线程中这样做,只需确保只有一个线程一次线程执行以下操作:

    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;
        }
      }
    
    }
    

    创建一个类的实例,并将其交给每个线程。现在他们可以各自推进进度并获得下一个计数器值。

    db和网络听起来像是你的瓶颈……你进行了基准测试吗?你说得很对。基准测试是尽快计划的。谢谢,问题N1是相互关联的。增量正是我需要的。第二个问题是我可以(通常)创建带有时间戳的记录数组,但它很大而且(如果可能的话)我想检查流生成的时间戳。生成规则非常简单:只需为每个后续记录提前一个特定间隔的时间戳。@BreakPhreak:对于第二个问题,我仍然不明白;也许您可以发布在单线程情况下您想要的代码?record.setTimestamp(timestamp=timestamp.AddSeconds(1));但实际上,谢谢-我刚刚想出了第二部分的公式解决方案。@BreakPhreak:也许你可以使用。一切都很好,但问题仍然存在:我可以在同步器中添加一个时间戳字段,并在每次前进时提取它。这是你的意思还是有一种更理想的方法来处理这个问题?
    int counter = 0;
    void IncreaseCounter()
    {
        Interlocked.Increment(ref counter);
    }
    
    int GetCounter()
    {
        return Interlocked.Read(ref counter);
    }
    
    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;
        }
      }
    
    }