Форум по программированию Delphi Sources

 



Вернуться   Форум по программированию Delphi Sources > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 16.11.2019, 22:12
darkwellroad darkwellroad вне форума
Прохожий
 
Регистрация: 30.08.2013
Сообщения: 6
Версия Delphi: Delphi XE4
Репутация: 10
Вопрос Вызов одной DLL из нескольких потоков

Привет всем. Не спрашивайте зачем

При создании одного потока - все работает прекрасно и без ошибок. Если потоков 2 и больше - либо вылетает, либо сыпется различного рода ошибками, типа EAccessViolation или EInvalidPointer. Буду очень благодарен, если направите мысли в нужное русло! Всем спасибо!

Код DLL:
Код:
library gear;
 
uses
  System.SysUtils,
  System.Net.HttpClientComponent,
  System.Net.HttpClient,
  System.Net.URLClient;
 
{$R *.res}
 
function Execute: Integer; stdcall;
var
  PResponse: IHTTPResponse;
begin
  with TNetHTTPClient.Create(nil) do
    try
      PResponse := GET('https://www.google.com/');
      Result := PResponse.StatusCode;
    finally
      PResponse := nil;
      free
    end;
end;
 
exports Execute;
 
begin
 
end.
Код потока:
Код:
unit TestThreadUnit;
 
interface
 
uses
  Windows,
  SysUtils,
  Classes;
 
type
  TExecute = function(): Integer;
 
  TestThread = class(TThread)
  protected
    I: Integer;
    procedure Execute; override;
  public
    constructor Create;
    procedure Sync;
  end;
 
implementation
 
uses TestUnit;
 
constructor TestThread.Create;
begin
  inherited Create(false);
end;
 
 
procedure TestThread.Execute;
var
  hndDLLHandle: THandle;
  Ex: TExecute;
begin
  try
    hndDLLHandle := loadLibrary('gear.dll');
    if hndDLLHandle <> 0 then
      begin
        @Ex := getProcAddress(hndDLLHandle, 'Execute');
        if addr(Ex) <> nil then
          I := Ex()
        else
          I := -1;
      end
    else
      I := -1;
  finally
    freeLibrary(hndDLLHandle);
    Synchronize(Sync);
  end;
end;
 
procedure TestThread.Sync;
begin
  TestForm.Memo1.Lines.Add(I.ToString);
end;
 
end.
Работаю так:
Код:
unit TestUnit;
 
interface
 
uses
 
  System.Classes,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.StdCtrls;
 
type
 
  TTestForm = class(TForm)
    ThreadButton: TButton;
    Memo1: TMemo;
    procedure ThreadButtonClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  TestForm: TTestForm;
 
implementation
 
uses TestThreadUnit;
 
{$R *.dfm}
 
procedure TTestForm.ThreadButtonClick(Sender: TObject);
var
  m: integer;
begin
  // for m := 0 to 1 do
  TestThread.Create.FreeOnTerminate := true;
end;
 
end.
Ответить с цитированием
  #2  
Старый 18.11.2019, 21:03
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,518
Версия Delphi: 7, XE3, 10.2
Репутация: 49088
По умолчанию

1. В описании типа функции так же укажи stdcall. В твоем случае это не должно быть проблемой, т.к. это больше влияет на передачу параметров, но все-таки.
2. Мне не нравится, что ты пытаешься грузить библиотеку несколько раз. Попробуй вынести загрузку библиотеки и ее освобождение из потока (пока для проверки - сделай глобальную переменную для хэндла, а саму загрузку и выгрузку просто вынеси в секции initialize и finalize модуля, если все полечится, то потом можно будет переписать почеловечески).
Ответить с цитированием
  #3  
Старый 22.11.2019, 17:16
darkwellroad darkwellroad вне форума
Прохожий
 
Регистрация: 30.08.2013
Сообщения: 6
Версия Delphi: Delphi XE4
Репутация: 10
По умолчанию

Цитата:
Сообщение от lmikle
1. В описании типа функции так же укажи stdcall. В твоем случае это не должно быть проблемой, т.к. это больше влияет на передачу параметров, но все-таки.
2. Мне не нравится, что ты пытаешься грузить библиотеку несколько раз. Попробуй вынести загрузку библиотеки и ее освобождение из потока (пока для проверки - сделай глобальную переменную для хэндла, а саму загрузку и выгрузку просто вынеси в секции initialize и finalize модуля, если все полечится, то потом можно будет переписать почеловечески).
Получилось только после того, как я все перенес в BPL. Всеми остальными способами не получалось. Теперь другая проблема. На другом компьютере требудет rtl260.bpl и borlndmm.dll. Таскать их с собой как то.... НУ такое. ООчень вам благодарен
Runtime Packages галка снята

Последний раз редактировалось darkwellroad, 22.11.2019 в 17:19.
Ответить с цитированием
  #4  
Старый 22.11.2019, 19:49
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,518
Версия Delphi: 7, XE3, 10.2
Репутация: 49088
По умолчанию

BPL - значит сами компоненты зависимы от VCL.
Если тебе надо просто получитьт код возврата, то попробуй вместо этих компонентов воспользоваться Indy (да, придется таскать за собой пару dll для поддержки ssl, ну или нарыть код для включеия их в exe/dll, но они не большие).
Ответить с цитированием
Ответ



Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 19:14.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources", 2004-2019

ВКонтакте   Facebook   Twitter