Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / DLL - Thread и безудержный секс / 25 сообщений из 89, страница 1 из 4
05.10.2019, 16:10
    #39872026
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
Доброго дня господа !

Имею первичную постановку
1.Динамический вызов из библиотека DLL
2.Создаю пользовательский объект AddSpan
3.Основная функция объекта AddSpan это Execute
4.Поле объекта Thread, который может запуска Execute в потоке (по потребности)
5.Возврат значения RecordSet, по результатам выполнения (в примере возвращаю String)

Проблема при вызове в потоке, невозможно вернуть результат


Возможное решение
1. При создание AddSpan - фиксирую адрес ячейки

constructor TAddSpan.Create(aFile: String; aBars: TProgressBar; Terminate: TTerminate; var aSql: OleVariant);
...............
pSql:=@aSql;
................

2.При создании поля-потока, фикcирую родитель-объект
constructor TAddExec.Create(aHandleParent: TAddSpan; aExecute: TExecute; aTerminate: TTerminate);
................
HandleParent :=aHandleParent;
................

3.При окончании работы потока - уничтожаю родитель-объект, предварительно по адресу
передав результат выполнения функции Execute

procedure TAddExec.TerminateThread(Sender: TObject);
begin
HandleParent.pSql^:=OleVariant(HandleParent.SQL); - возврат результата
HandleParent.Free;
HandleParent:=Nil;
AddTerminate(Sender); - доп. процедура которая в основной форме
end;

Не нравится
- " окончания работы потока - уничтожаю родитель-объект"
уничтожить из дочери - родителя - не есть архитектурно !

- слишком сексуально !!!! и много извращений связанных с адресами переменных

Но другого решения увы не нашел.
О великие ГУРУ прошу подсказать более технологичное решение (можно с примером)

Заранее благодарен !

Имею код вызова
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
Create_AddSpan: function(aFile: String; aList: String; aThread: Boolean; aBar: TProgressBar; Terminate: TTerminate; var aSql: OleVariant): Integer; stdcall;

@Create_AddSpan:=nil;
LibHandle := LoadLibrary('MyLibrary.dll');
if LibHandle >= 32 then begin
  @Create_AddSpan:=GetProcAddress(LibHandle,'Create_AddSpan');
  if @Create_AddSpan<>nil then Create_AddSpan(aFile,aList,True,pbMain,TerminateThread,ovSql);
end;
FreeLibrary(LibHandle); //если поток уничтожать нельзя



Пользовательский класс

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
unit AddSpan;

type
  POleVariant = ^OleVariant;
  TAddSpan    = class;
  TExecute    = procedure of object;
  TTerminate  = procedure(Sender: TObject) of object;


  TAddExec = class(TThread)
  private
    ParentExecute: TExecute;
    AddTerminate:  TTerminate;
   protected
    //
  public
    HandleParent: TAddSpan;
    constructor   Create(aHandleParent: TAddSpan; aExecute: TExecute; aTerminate: TTerminate);
    procedure     Execute; override;
    procedure     TerminateThread(Sender: TObject);
  published
    //
  end;

  TAddSpan = class(TObject)
  private
    thExec:   TAddExec;
    mtExit:   TTerminate;
    pSql:     POleVariant;
 protected
    //
 public
    SQL:        String;
    constructor Create(aFile: String; aBars: TProgressBar; Terminate: TTerminate; var aSql: OleVariant); virtual;
    procedure   Execute;
    procedure   ExecuteThread;
  published
    //
  end;

implementation

  function Create_AddSpan(aFile: String; aList: String; aThread: Boolean; aBar: TProgressBar; Terminate: TTerminate; var aSql: OleVariant): Integer;
  var A: TAddSpan;

      I: Integer;
      L: Boolean;
      S,List: String;

  begin
    A:=TAddSpan.Create(aFile,aBar,Terminate,aSql);
    .........................
    if aThread then A.ExecuteThread else A.Execute;

    //если поток уничтожать нельзя - 3-и строки это ошибка
    aSql:=OleVariant(A.sSql);
    A.Free;
    A:=Nil;
  end;

  constructor TAddExec.Create(aHandleParent: TAddSpan; aExecute: TExecute; aTerminate: TTerminate);
  begin
    Inherited Create(True);
    HandleParent   :=aHandleParent;
    ParentExecute  :=aExecute;
    AddTerminate   :=aTerminate;
    FreeOnTerminate:=True;
    OnTerminate    :=TerminateThread;
  end;

  procedure TAddExec.TerminateThread(Sender: TObject);
  begin
    HandleParent.pSql^:=OleVariant(HandleParent.SQL);
    HandleParent.Free;
    HandleParent:=Nil;
    AddTerminate(Sender);
  end;

  procedure TAddExec.Execute;
  begin
    ParentExecute;
  end;

  constructor TAddSpan.Create(aFile: String; aBars: TProgressBar; Terminate: TTerminate; var aSql: OleVariant);
  var I: Integer;
      S: TArrayStr;
      Sect,Note: String;
  begin
    Inherited Create;
    .........................
    mtExit:=Terminate;
    pSql:=@aSql;
  end;

  destructor TAddSpan.Destroy;
  begin
    .................
    inherited;
  end;

  procedure TAddSpan.Execute;
  var I: Integer;
      L: Boolean;

  begin
    CoInitialize(nil);
    try
      SQL:='значение этой переменной нужно вернуть';
    ................................
    end;
    CoUninitialize;
  end;

  procedure TAddSpan.ExecuteThread;
  begin
    thExec:=TAddExec.Create(Self,Self.Execute,Self.mtExit);
    thExec.Resume;
  end;

end.
...
Рейтинг: 0 / 0
05.10.2019, 16:18
    #39872027
ёёёёё
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
HOME_X,

используй сообщения. Рабочая нить выделяет память под результат и, выполнив работу, посылает сообщение потребителю. Потребитель последовательно выгребает сообщения из очереди, обрабатывает и освобождает память.
Сто раз описано, в том числе и здесь.
...
Рейтинг: 0 / 0
05.10.2019, 16:51
    #39872031
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
ёёёёёHOME_X,
Сто раз описано, в том числе и здесь.


Если желаете помочь - пишите четко, и на конкретном примере
Если НЕ желаете помочь НЕ пишите в 101 раз...

Спасибо
...
Рейтинг: 0 / 0
05.10.2019, 16:58
    #39872032
ёёёёё
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
HOME_X,

а что тебе непонятно, конкретно? Не знаешь, что такое сообщения, сообщения Windows, очередь сообщений нити, ... - что?
...
Рейтинг: 0 / 0
05.10.2019, 17:32
    #39872039
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
ёёёёёHOME_X,

а что тебе непонятно, конкретно? Не знаешь, что такое сообщения, сообщения Windows, очередь сообщений нити, ... - что?


Изложите Ваши мысли в конкретный программный код

Спасибо
...
Рейтинг: 0 / 0
05.10.2019, 17:59
    #39872048
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
HOME_XИмею первичную постановку
1.Динамический вызов из библиотека DLL

Твой код где: в основном приложении или в библиотеке? Потоки где: в основном приложении
или библиотеке?

Во втором случае обломись, потоки и DLL это тема на которой обламывают зубы даже зубры,
новичкам туда лучше не лезть вообще.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
05.10.2019, 18:54
    #39872055
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
Dimitry SibiryakovHOME_XИмею первичную постановку
1.Динамический вызов из библиотека DLL

Твой код где: в основном приложении или в библиотеке? Потоки где: в основном приложении
или библиотеке?

Во втором случае обломись, потоки и DLL это тема на которой обламывают зубы даже зубры,
новичкам туда лучше не лезть вообще.


1.
- пользовательский объект находиться в DLL
- в этом объекте находиться метод Execute, вызываться как линейно так и в потоке
- в этом объекте находиться метод ExecuteThread, который "заворачивает" Execute
и выполняет его в потоке
- этот объект возвращает тип RecordSet (OleVariant - так как эта DLL будет использоваться
НЕ только исходниками Delphi)
- вызывающий код, находиться в основном приложении , вызов объекта осуществляется динамически
(LoadLibrary->FreeLibrary)

Если есть еще вводные вопросы - прошу Вас.....

P.S. "зубы даже зубры"
Зубрами не рождаются, "горшки не только программисты обжигают"
Во времени особо не ограничен, если конкретизируете тему "потоки и DLL" (примеры , статьи , ссылки)
узнать новое и практически применить знания буду рад.


Спасибо за уделенное время.
...
Рейтинг: 0 / 0
05.10.2019, 18:55
    #39872056
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
Dimitry SibiryakovHOME_XИмею первичную постановку
1.Динамический вызов из библиотека DLL

Твой код где: в основном приложении или в библиотеке? Потоки где: в основном приложении
или библиотеке?

Во втором случае обломись, потоки и DLL это тема на которой обламывают зубы даже зубры,
новичкам туда лучше не лезть вообще.

Какая разница, где поток в основном приложении или в DLL? Потоку в общем-то насрать, где крутиться.
Проблема в менеджере памяти и общих данных.
Есть особенности работы при инициализации DLL, но в целом потоку без разницы.

А вообще тема норм, хорошо названа, побольше бы таких тем
...
Рейтинг: 0 / 0
05.10.2019, 19:02
    #39872060
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
HOME_X,
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
 function Create_AddSpan(aFile: String; aList: String; aThread: Boolean; aBar: TProgressBar; Terminate: TTerminate; var aSql: OleVariant): Integer;
  var A: TAddSpan;

      I: Integer;
      L: Boolean;
      S,List: String;

  begin
    A:=TAddSpan.Create(aFile,aBar,Terminate,aSql);
    .........................
    if aThread then A.ExecuteThread else A.Execute;

    //если поток уничтожать нельзя - 3-и строки это ошибка
    aSql:=OleVariant(A.sSql);
    A.Free;
    A:=Nil;
  end;



А кто поток ждать будет? А вообще это лучше реализовывать на интерфейсах.
...
Рейтинг: 0 / 0
05.10.2019, 19:37
    #39872067
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
ziv-2014Какая разница, где поток в основном приложении или в DLL?
А вообще тема норм, хорошо названа, побольше бы таких тем

....OleVariant - так как эта DLL будет использоваться НЕ только исходниками Delphi

Основное приложение (оно же Delphi, оно же VBS, оно же VBA, оно же ............)
ссылается на логически законченный объект, который в DDL

Побольше технологически грамотных решений и понимания тоже не помешает..

А кто поток ждать будет?
А вообще это лучше реализовывать на интерфейсах.

В Delphi - основная форма - AddTerminate

Код: pascal
1.
2.
3.
4.
5.
6.
7.
 procedure TAddExec.TerminateThread(Sender: TObject);
  begin
    HandleParent.pSql^:=OleVariant(HandleParent.SQL);
    HandleParent.Free;
    HandleParent:=Nil;
    AddTerminate(Sender); - это процедура основной формы, которая обновить 'дерево" штатки
  end;



Буду рад осмотреть Ваш вариант решения
если начальных вводных недостаточно - прошу вопрошать..
...
Рейтинг: 0 / 0
05.10.2019, 19:54
    #39872071
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
[quot HOME_X]
Основное приложение (оно же Delphi, оно же VBS, оно же VBA, оно же ............)
[/src]

Добавлю что исходя из вызывающего приложения в DLL реализовано несколько сценариев вызова,
в том числе и COM - сервер, ряд местных особенностей и настроек ПК, требуют простой реализации
(например DLL в текущей папке вместе с EXE или по заданному путь в "открытом" коде VBA)
так как нет доступа к изменению системной переменой Path, и невозможно изменить системный реестр

Т.е. у меня ПОКА стоит первичная задача - DLL -> Thread -> возврат RecordSet.....
...
Рейтинг: 0 / 0
05.10.2019, 21:24
    #39872084
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
ziv-2014Есть особенности работы при инициализации DLL, но в целом потоку без разницы.

При инициализации-то это ещё цветочки. Выгрузка это то место где из-под потока может
внезапно исчезнуть его код, не говоря уже о поддерживающей RTL.

HOME_XТ.е. у меня ПОКА стоит первичная задача - DLL -> Thread -> возврат RecordSet.....

Обломись. Так работать не будет даже если ты перечитаешь целый MSDN. Тут нужен COM-сервер.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
05.10.2019, 21:26
    #39872086
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
HOME_X,
String, TObject и другие типы - тоже поддерживаются VBA?
Что-то не похоже на COM.
...
Рейтинг: 0 / 0
05.10.2019, 21:31
    #39872089
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
При инициализации-то это ещё цветочки. Выгрузка это то место где из-под потока может
внезапно исчезнуть его код, не говоря уже о поддерживающей RTL.

1. Загрузили DLL
2. Запустили поток в отдельной процедуре
3. Остановили поток, убедились, что он остановлен полностью.
4. Выгрузили DLL
Как то так? А еще желательно скомпилировать dll и exe с одним bpl пакетом, чтобы не маятся с менеджером памяти.
...
Рейтинг: 0 / 0
05.10.2019, 21:36
    #39872090
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
HOME_X,
Проблема при вызове в потоке, невозможно вернуть результат

У вас корявый код, надо ждать, когда выполнится поток и только потом получать результат.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
function Create_AddSpan(aFile: String; aList: String; aThread: Boolean; aBar: TProgressBar; Terminate: TTerminate; var aSql: OleVariant): Integer;
  var A: TAddSpan;

      I: Integer;
      L: Boolean;
      S,List: String;

  begin
    A:=TAddSpan.Create(aFile,aBar,Terminate,aSql);
    .........................
    if aThread then begin 
      A.ExecuteThread; 
      A.WaitFor; //Надо ждать результат 
    end else A.Execute;

    //если поток уничтожать нельзя - 3-и строки это ошибка
    aSql:=OleVariant(A.sSql); //??? В A - это результат?
    A.Free;
    A:=Nil;
  end;



По уму надо использовать COM интерфейсы. А не вот это все. Тем более для VBA.
Если же вызывать на прямую из VBA, то VBA не понимает делфи объекты, а стринги воспринимает как Ansi. String в последних версиях делфи уникодный.
...
Рейтинг: 0 / 0
05.10.2019, 21:38
    #39872091
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
Dimitry SibiryakovHOME_XТ.е. у меня ПОКА стоит первичная задача - DLL -> Thread -> возврат RecordSet.....

Обломись. Так работать не будет даже если ты перечитаешь целый MSDN. Тут нужен COM-сервер.

В VBA на прямую можно вызывать функции из DLL без COM сервера.
...
Рейтинг: 0 / 0
05.10.2019, 21:41
    #39872093
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
Только автор знатно на говнокодил, поэтому поэтому имеет безудержный секс, который в будущем может только усиливаться.
...
Рейтинг: 0 / 0
05.10.2019, 22:07
    #39872097
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
ziv-2014В VBA на прямую можно вызывать функции из DLL без COM сервера.

И получать из них RecordSet? Может, конечно, но зачем в этой картине Delphi?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
05.10.2019, 22:09
    #39872098
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
Dimitry Sibiryakovziv-2014Есть особенности работы при инициализации DLL, но в целом потоку без разницы.

При инициализации-то это ещё цветочки. Выгрузка это то место где из-под потока может
внезапно исчезнуть его код, не говоря уже о поддерживающей RTL.

HOME_XТ.е. у меня ПОКА стоит первичная задача - DLL -> Thread -> возврат RecordSet.....

Обломись. Так работать не будет даже если ты перечитаешь целый MSDN. Тут нужен COM-сервер.


Да в общем все работает ....
Мне не понравилась работа с адресами и уничтожением "родителя в дочере"

Буду еще тестировать... может всплывуют ошибки
...
Рейтинг: 0 / 0
05.10.2019, 22:10
    #39872099
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
ziv-2014HOME_X,
String, TObject и другие типы - тоже поддерживаются VBA?
Что-то не похоже на COM.

Использую OLEVariant ....
...
Рейтинг: 0 / 0
05.10.2019, 22:12
    #39872102
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
Dimitry Sibiryakovziv-2014В VBA на прямую можно вызывать функции из DLL без COM сервера.

И получать из них RecordSet? Может, конечно, но зачем в этой картине Delphi?

Автор собрался получать данные в String->WideString->OleVariant, и простые типы можно и так.
Я бы сделал через PAnsiChar - так быстрее, и надо память выделять правильно.
А так конечно боль RecordSet передавать. Умнее запихать интерфейсы. Может ли VBA вызывать интерфейсы без IDispatch - если умеет то, можно обойтись малой кровью. А если не умеет, то лучше сделать COM Server - это добро можно будет использовать в любом месте без проблем.
...
Рейтинг: 0 / 0
05.10.2019, 22:14
    #39872103
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
ziv-2014HOME_X,
Проблема при вызове в потоке, невозможно вернуть результат

У вас корявый код, надо ждать, когда выполнится поток и только потом получать результат.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
function Create_AddSpan(aFile: String; aList: String; aThread: Boolean; aBar: TProgressBar; Terminate: TTerminate; var aSql: OleVariant): Integer;
  var A: TAddSpan;

      I: Integer;
      L: Boolean;
      S,List: String;

  begin
    A:=TAddSpan.Create(aFile,aBar,Terminate,aSql);
    .........................
    if aThread then begin 
      A.ExecuteThread; 
      A.WaitFor; //Надо ждать результат 
    end else A.Execute;

    //если поток уничтожать нельзя - 3-и строки это ошибка
    aSql:=OleVariant(A.sSql); //??? В A - это результат?
    A.Free;
    A:=Nil;
  end;



По уму надо использовать COM интерфейсы. А не вот это все. Тем более для VBA.
Если же вызывать на прямую из VBA, то VBA не понимает делфи объекты, а стринги воспринимает как Ansi. String в последних версиях делфи уникодный.

Этих строк не должно быть именно здесь
Они в событии OnTerminate

aSql:=OleVariant(A.sSql); //??? В A - это результат?
A.Free;
A:=Nil;

а если ставить WaitFor - тормознете основную форму - тогда нет смысла в потоке
...
Рейтинг: 0 / 0
05.10.2019, 22:17
    #39872104
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
ziv-2014HOME_X,
По уму надо использовать COM интерфейсы.


Их надо регистрировать в OS - системный реестр закрыт от изменений
а использовать просто DLL возможно почти вседа
...
Рейтинг: 0 / 0
05.10.2019, 22:19
    #39872105
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
HOME_X,
а если ставить WaitFor - тормознете основную форму - тогда нет смысла в потоке
Тогда ни как, меняйте подход. Вы как результат дождетесь? Можно использовать колбеки, но как их реализовать в VBA я не знаю.
...
Рейтинг: 0 / 0
05.10.2019, 22:19
    #39872106
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Thread и безудержный секс
ziv-2014В VBA на прямую можно вызывать функции из DLL без COM сервера.


Именно так - что с успехом протестировал (но на тот момент быз потока)
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / DLL - Thread и безудержный секс / 25 сообщений из 89, страница 1 из 4
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]