0

目前,我正在寻找一种解决方案来加速我的代码。我有一个具有不同几何组件(点、多边形)的数据库。每个结构都由多个属性给出,称为 Con_Number(默认值:0)、LayerName、单个索引 (ObjectIndex)。因此每个实例的 Con_Number 应该是相同的值...

  • 在同一层上重叠的结构。
  • 在相邻层上重叠的结构。

我使用 STIntersects 命令获取重叠实例。

sqlString := 'declare @g geometry select @g = Geom from obj where ObjectIndex = :index select ObjectIndex, Con_Number from obj WITH(index(idx_Spatial)) where Geom.STIntersects(@g) = 1 and ObjectLayerName in (' + QuotedStrList(neighbourLayers) + ')';

我试图在遍历某一层的所有元素的并行循环中执行此算法。之后,我在单独的连接/查询上为每个实例运行 SqlCommand。结果将根据不同 con_number 的数量进行不同的处理。最后但同样重要的是,重叠结构的 Con_number 将被更新。

  1. 步骤:找到所有重叠的元素!
  2. 步骤:更新重叠元素的 Con_Number!

    Parallel.ForEach<Integer>(indexList)
          .NumTasks(ThreadCount).Execute(
          procedure(const item: Integer)
    var
        Con_Number: Integer; 
        Con_List: TIntegerList;
    begin
    //Create TADOConnection and TADOQueries
    
        // 1.STEP: get signals of all overlapping elements
        ADOQueryOverlap.SQL.Text := sqlString;
        ADOQueryOverlap.ParamCheck := True;
        ADOQueryOverlap.Parameters.ParamByName('index').DataType := ftInteger;
        ADOQueryOverlap.Parameters.ParamByName('index').Value := item;
        ADOQueryOverlap.Open;
        ADOQueryOverlap.First;
    
        while not ADOQueryOverlap.Eof do
        begin
          indexThreadList.add(ADOQueryOverlap.FieldByName('ObjectIndex')
            .AsInteger);
          Con_Number:= ADOQueryOverlap.FieldByName('Con_Number').AsInteger;
          if (Con_List.IndexOf(Con_Number) < 0) and (Con_Number > 0) then
          begin
            Con_List.add(Con_Number);
          end;
          ADOQueryOverlap.next;
        end;
    
    //2. STEP UPDATE CON_NUMBER
    
    if indexThreadList.Count > 0 then
    begin
      // elements have no Con_Number -> Assign new Con_Number to overlapping elements
      if signalList.Count = 0 then
      begin
        InterlockedIncrement(FId);
        ADOQueryWriteBack.SQL.Text := 'update obj set Con_Number = ' +
          FId.ToString + ' where ObjectIndex in (' +
          indexThreadList.AsString + ')';
        ADOQueryWriteBack.ExecSQL;
      end;
      // one Con_Number exist -> write that number to all other objects
      if signalList.Count = 1 then
      begin
        ADOQueryWriteBack.SQL.Text := 'update obj set Con_Number = ' +
          Con_List.Items[0].ToString + ' where ObjectIndex in (' +
          indexThreadList.AsString + ')';
        ADOQueryWriteBack.ExecSQL;
      end;
      // more than 1 Con_Number exists -> Take one Con_Number and overwrite other Con_Numbers 
      if signalList.Count > 1 then
      begin
        ADOQueryWriteBack.SQL.Text := 'update obj set Con_Number = ' +
          Con_List.Items[0].ToString + ' where ObjectIndex in (' +
          indexThreadList.AsString + ') or Con_Number in (' +
          Con_List.GetListAsStringFromIndex(1) + ')';
        ADOQueryWriteBack.ExecSQL;
      end;
    end;
    

目前,我试图获得更好的表现。此外,线程在一段时间(几个小时)后崩溃。你认为多线程适合我的应用吗?你有其他改进的想法吗?

4

0 回答 0