Перейти к содержанию
Fire Monkey от А до Я

antigrav

Пользователи
  • Постов

    25
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные antigrav

  1. Применено так, как вы предложили. В методе FormClose. В тестовом примере оказывается 

    ThreadPoolStats.IdleWorkerThreadCount=3

    и 

    ThreadPoolStats.WorkerThreadCount=3

    Условие не выполняется, программа закрывается с утечкой.

    Насколько я понял, ThreadPoolStats.IdleWorkerThreadCount хранит кол-во потоков, ожидающих завершения. 

    Если, например, изменить условие на 

    if ThreadPoolStats.IdleWorkerThreadCount>0

    то приложение просто невозможно закрыть.

  2. Уважаемый Slym, к сожалению предложенный способ результата не дал. Если я правильно понял, условие  

    ThreadPoolStats.IdleWorkerThreadCount<>ThreadPoolStats.WorkerThreadCount

    является признаком того, что не все таски завершены. При тестировании приложения это условие не выполняется (то есть все такси завершены?), управление передается деструктору главной формы приложения, в котором дается команда на удаление пользовательских объектов. Пользовательские объекты удаляются. Затем выдается сообщение об утечке памяти и приложение закрывается.

  3. Здравствуйте, коллеги.

    Пишу метод десериализации для считывания данных из файла и создания соответствующего объекта в памяти. Для того, чтобы пользователь не скучал, загружаю данные в отдельном потоке, а в главном запускаю TAniIndicator. Данные считываются, объект создается, AniIndicator работает. Но при попытке завершения приложения получаю утечку памяти (см. рис.). Пользовательские объекты я удаляю перед закрытием приложения, но в памяти остаются системные объекты, в том числе из библиотеки PPL. Сокращенный код метода загрузки данных ниже. С чем может быть связана утечка? Для детектирования утечек использую команду ReportMemoryLeaksOnShutdown := True. Если дополнительный поток не использую, утечек нет.

    image.png.8b00fea0b153f4b4fca7da6dc12a6945.png

    procedure LoadProjectFromFile(AFileName: string);
    var
      fut: IFuture<TComponent>;
      cmp: TComponent;
    begin
      AniIndic.Enabled := True;
      AniIndic.Visible := True;
      fut := TTask.Future<TComponent>(
        function: TComponent
        begin
          Result := LoadFromFile(AFileName);
        end
      );
      TTask.Run(
        procedure
        begin
          fut.Start;
          cmp := fut.Value;
          {$REGION 'После загрузки в главном потоке'}
          TThread.Synchronize(nil,
            procedure
            begin
              AniIndic.Enabled := False;
              AniIndic.Visible := False;
              if Assigned(cmp) then
              begin
                if cmp is TCAMProject then
                begin
                  fProject := cmp as TCAMProject;
                  // здесь всякие действия
                  if Assigned(OnFinishedLoadProject) then
                  begin
                    OnFinishedLoadProject(nil);
                  end;
                end
              end
            end
          )
          {$ENDREGION}
        end
      );
    end;

  4. Здравствуйте!

    Пишу алгоритм с параллельными вычислениями. Один из объектов является разделяемым ресурсом и хотелось бы его клонировать. Объект достаточно сложный и использует другие объекты. Возникла идея применения механизма сериализации/десериализации. Примерный код ниже.

    function Cloning(RootObject: TComponent): TComponent;
    var
      MemStream: TMemoryStream;
    begin
      MemStream := TMemoryStream.Create;
      try
        MemStream.WriteComponent(RootObject);
        MemStream.Position := 0;
        Result := MemStream.ReadComponent(RootObject);
      finally
        MemStream.Free;
      end;
    end;


    Данный код, однако, не дает нужного результата. Исходный компонент RootObject и Result, в итоге, ссылаются на одну и ту же область памяти. Может ли уважаемое сообщество предложить какие-то решения?

  5. Здравствуйте!

    Имею следующий фрагмент кода:

     

    fines: array of Extended;

    TParallel.For(0, Pred(count),
        procedure(index: Integer)
        begin
             fines[index] := CalculateFine(Index);
             TThread.Synchronize(nil,
                 procedure
                 begin
                     Memo.Lines.Add('ThreadID = ' + TThread.CurrentThread.ThreadID.ToString);

                end);

        end);

     

    В логе получаю один и тот же номер ThreadID для всех значений index. Разве не должны быть созданы count потоков, каждый со своим ID?

  6. Вижу, что посты от 15-го года. Мне понадобился целочисленный TScrollBar сейчас и именно в FMX. Похоже, ничего не изменилось. Ползунок меняет значение не на целую величину, а на дробную. Нужно писать своего потомка для компонента или кто-нибудь знает более простое решение?

  7. Здравствуйте! В OpenGL и DirectX есть возможность при работе с буфером глубины (z-буфер) выбирать различные варианты приоритета для конфликтующих пикселей, то есть таких, которые находятся в сцене на одинаковом расстоянии от наблюдателя. В OpenGL, например, использовалась команда glDepthFunc(GLenum func), в которую можно было передать константу для выбора одного из двух соперничающих пикселей. Имеется ли подобная команда в FMX? 

  8. Я про этот код. Главный поток.

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Test;
    end;

    procedure TForm1.Test;
    const
      n = 200;
    var
      I: Integer;
    begin
      ProgressBar1.Min := 0;
      ProgressBar1.Max := n - 1;
      for I := 0 to n - 1 do
      begin
        ProgressBar1.Value := I;
        sleep(10);
      end;
    end;

    Я нажимаю кнопку и ожидаю, что после ее нажатия ProgressBar1 постепенно, в цикле, будет заполняться. Но этого не происходит. После нажатия я вижу пустой ProgressBar1 и только спустя время 10*200, в конце цикла, вижу уже заполненный ProgressBar1. Постепенного заполнения ProgressBar не происходит.

    Такой же процесс в дополнительном потоке, однако, работает корректно. Точнее, так как мне нужно.

  9. Спасибо за ссылку! Полезно. Добавил в избранное. 

    Про синхронизацию я знаю, поэтому сам был удивлен, что запись напрямую в компонент из доп потока сработала.

    Вот такой код, с синхронизацией, для второй кнопки тоже работает:

    procedure TForm1.Button2Click(Sender: TObject);
    begin
      TTask.Run(
        procedure
        const
          n = 200;
        var
          I: Integer;
        begin
          TThread.Synchronize(nil,
            procedure
            begin
              ProgressBar1.Min := 0;
              ProgressBar1.Max := n - 1;
            end
          );
          for I := 0 to n - 1 do
          begin
            TThread.Synchronize(nil,
              procedure
              begin
                ProgressBar1.Value := I;
              end
            );
            sleep(10);
          end;
        end
      );
    end;

     

    Вопрос мой такой: почему точно также не работает код для основного потока (кнопка 1), то есть почему не видно постепенного заполнения ProgressBar в главном потоке? 

     

  10. Коллеги, здравствуйте!

    Есть максимально простая задача: в длительном цикле необходимо так или иначе показывать пользователю номер текущей итерации. Делаю это с помощью ProgressBar. При этом если использую главный поток (кнопка 1), то результат вижу по окончании цикла, когда ProgressBar уже заполнен, а когда использую дополнительный поток (кнопка 2) - вижу постепенное заполнение ProgressBar, чего и пытаюсь добиться в главном потоке. Почему так? Такое ощущение, что от меня ускользает какой-то важный принцип использования FMX. Кто-нибудь может объяснить происходящее? Код ниже. Спасибо!

     

    unit Unit1;

    interface

    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
      FMX.Controls.Presentation;

    type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        ProgressBar1: TProgressBar;
        Button3: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
      private
        procedure Test;
      public
        { Public declarations }
      end;

    var
      Form1: TForm1;

    implementation

    uses

      System.Threading;

    {$R *.fmx}

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Test;
    end;

    procedure TForm1.Button2Click(Sender: TObject);
    begin
      TTask.Run(
        Test
      );
    end;

    procedure TForm1.Button3Click(Sender: TObject);
    begin
      ProgressBar1.Value := 0;
    end;

    procedure TForm1.Test;
    const
      n = 200;
    var
      I: Integer;
    begin
      ProgressBar1.Min := 0;
      ProgressBar1.Max := n - 1;
      for I := 0 to n - 1 do
      begin
        ProgressBar1.Value := I;
        sleep(10);
      end;
    end;

    end.
     

  11. Олег, не могли бы Вы рассказать, какими материалами (документация, книги, интернет-ресурсы и пр.) пользовались для 3D визуализации карданного вала?

  12. Коллеги, здравствуйте! Прошу поделиться ссылками на работу с классом TVertexBuffer. Книгу Осипова читал, но информации для решения моих задач не нашел. Может есть что-то еще по 3D работе с Fire-Monkey? Спасибо!

×
×
  • Создать...