Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 25.05.2018, 00:18   #1
LD-One
Пользователь
 
Регистрация: 18.03.2012
Сообщений: 47
По умолчанию Запуск процедуры хранящейся в массиве из потока - Delphi 10.1

Столкнулся вот с какой проблемой, я храню процедуры в массиве дабы в дальнейшем запускать их в новом потоке, но выполнение программы останавливается на ее запуске.

Код:
unit workByte;

interface

uses
    Windows, Variants, IOUtils, System.SysUtils, StrUtils, Debug, System.Types, Classes;



type
    tProc = procedure(param : string);
    TWorkByte = class
    public
    procedure AddThread(funcName:tProc; param:string);
    private
    procedure SetArgs(funcName: tProc; param:string; ID:integer);
end;

TMyThread = class(TThread)
    public
    private
    protected
    procedure Execute; override;
end;

var
   Thread:array of TMyThread;
   Functions:array of tProc;
   Params:array of string;
   Logger: TDebug;
   csCriticalSection: TRTLCriticalSection;

implementation



{ TWorkByte }

procedure TWorkByte.SetArgs(funcName: tProc; param: string; ID:integer);
var
   sizeOfFunc, sizeOfParam: integer;
begin
  sizeOfFunc := length(Functions);
  sizeOfParam := length(Params);
  SetLength(Functions, sizeOfFunc + ID);
  SetLength(Params, sizeOfParam + ID);
  Functions[ID] := funcName;
  Params[ID] :=  param;
  { Если тут вызвать Functions[ID](Params[ID]), то все корректно отработает разумеется }
end;


procedure TWorkByte.AddThread(funcName: tProc; param: string);
var
   sizeOfMassive, lastPosition, ID: integer;
begin
try
 sizeOfMassive := length(Thread);
 lastPosition := High(Thread);
 SetLength(Thread, sizeOfMassive + 1);
 Thread[lastPosition] := TMyThread.Create(False);
 ID := Thread[lastPosition].ThreadID;
 Logger.Write('Создание: '+IntToStr(ID));
 SetArgs(funcName, param, ID);
 Thread[lastPosition].Resume;
 Thread[lastPosition].Priority:=tpNormal;
except on e:Exception do
Logger.Write('Ошибка: ' + e.Message);
end;
end;


{ TMyThread }

procedure TMyThread.Execute;
var
   ThreadID: integer;
begin
Logger.Write('1');
  ThreadID := GetCurrentThreadID;
  Logger.Write('2');
  Logger.Write(Params[ThreadID]); //Вот тут прекращается работа программы, в дебаге 3 уже не выводит, если убрать то закончится выполнение на Functions[ThreadID](Params[ThreadID]);
  Logger.Write('3');
  Functions[ThreadID](Params[ThreadID]);
  Logger.Write('4');
  Logger.Write(IntToStr(GetCurrentThreadID));
end;

initialization
  InitializeCriticalSection(csCriticalSection);
finalization
  DeleteCriticalSection(csCriticalSection);

end.
В чем проблема? Возможно я каких-то тонкостей не знаю и поэтому оно не работает?
LD-One вне форума Ответить с цитированием
Старый 25.05.2018, 00:54   #2
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,656
По умолчанию

Цитата:
Сообщение от LD-One Посмотреть сообщение
В чем проблема? Возможно я каких-то тонкостей не знаю и поэтому оно не работает?
Какие в жопу тонкости? Ты обкурился?
У тебя Params - это массив, а ты пытаешься обратиться к нему по смещению
Код:
ThreadID := GetCurrentThreadID;
Это РАНДОМНОЕ число, блть!
Цитата:
Until the thread terminates, the thread identifier uniquely identifies the thread throughout the system.
Спать ложись.
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 25.05.2018, 01:03   #3
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,656
По умолчанию

А ваще, юзать дин. массивы для хранения указателей - это эрзац. Для этого понаписано 100500 классов - наследников TList и дженериков. TThreadList ваще стандартный класс со времён царя гороха.

Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 25.05.2018, 02:37   #4
northener
ПШП
Участник клуба
 
Регистрация: 15.07.2013
Сообщений: 1,859
По умолчанию

Добавлю только.
Столкнулся вот с какой проблемой, я храню процедуры в массиве дабы в дальнейшем запускать их в новом потоке, но выполнение программы останавливается на ее запуске.
Кода самой программы вы не привели. Привели только код дополнительного модуля.
northener вне форума Ответить с цитированием
Старый 25.05.2018, 07:50   #5
LD-One
Пользователь
 
Регистрация: 18.03.2012
Сообщений: 47
По умолчанию

Цитата:
Сообщение от min@y™ Посмотреть сообщение
Ты обкурился?
А ты? Угостишь? А то видимо мое веществе действует слабее твоего, так как напрочь отключает у человека функцию адекватного оказания помощи.


Цитата:
Сообщение от min@y™ Посмотреть сообщение
РАНДОМНОЕ число
Серьезно? Может мне в казино сыграть тогда? Я настолько фартовый, что в
Код:
ThreadID := GetCurrentThreadID;
и в
Код:
ID := Thread[lastPosition].ThreadID;
абсолютно всегда одинаковые числа.
Цитата:
Сообщение от min@y™ Посмотреть сообщение
обратиться к нему по смещению
Я одинаково обращаюсь к Params и в SetArgs и в Execute, то есть волшебный компилятор в SetArgs сначала к Params обращается как к массиву, а в Execute решает превратить его в нечто иное и обращаться по смещению? Я немного не понимаю, пришел с C# и там массивы работают адекватно, установка переменной Params[i] = '1111'; и так же можно получить что там лежит s = Params[i]; (s - 1111)
LD-One вне форума Ответить с цитированием
Старый 25.05.2018, 07:52   #6
LD-One
Пользователь
 
Регистрация: 18.03.2012
Сообщений: 47
По умолчанию

Цитата:
Сообщение от northener Посмотреть сообщение
Кода самой программы вы не привели
Я так понимаю, огромную роль тут играет код основной программы? Ну держи

Код:
unit Main;

interface

uses
    Windows, Debug, Variants, IOUtils, System.SysUtils, StrUtils, workByte;

    {Глобальные функции}
    //Точка входа
    procedure StartMain();
    procedure Test(str:string);

implementation

var
   Logger: TDebug;


procedure Test(str:string);
begin
 Logger.Write(str);
end;

procedure StartMain();
var
   wb: TWorkByte;
begin
    wb.AddThread(Test, 'Test');
end;

end.
Думаю теперь задача облегчена, после приведения кода основной программы.
LD-One вне форума Ответить с цитированием
Старый 25.05.2018, 07:57   #7
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,656
По умолчанию

Цитата:
Сообщение от LD-One Посмотреть сообщение
пришел с C# и там массивы работают адекватно
Иди обратно, откуда пришёл. У нас тут динамические массивы нумеруются с нуля и до "кол-ва элементов минус 1". А WinAPI-функция GetCurrentThreadID() возвращает уникальный для текущей сессии номер потока, который вызвал эту функцию.


Избавься от динамических массивов и проблема пропадёт. Ты тупо долбишься за пределы выделенной памяти или в неинициализированный элемент.
И с веществами завязывай. Это дорого и неэффективно.
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...

Последний раз редактировалось min@y™; 25.05.2018 в 08:14.
min@y™ вне форума Ответить с цитированием
Старый 25.05.2018, 08:10   #8
LD-One
Пользователь
 
Регистрация: 18.03.2012
Сообщений: 47
По умолчанию

Цитата:
Сообщение от min@y™ Посмотреть сообщение
для текущей сессии номер потока
TThreadList не дает возможности мне узнать ID потока. И как мне узнать ID потока в котором был запущен Execute? Суть даже не в самих потоках, я таким образом пытаюсь хранить имена функций и параметров, самый легкий вариант который я увидел, это забивать в массив под ID потока, потом уже в Execute по ID выполняющегося потока доставать эти данные из ID
LD-One вне форума Ответить с цитированием
Старый 25.05.2018, 08:28   #9
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,656
По умолчанию

Цитата:
Сообщение от LD-One Посмотреть сообщение
TThreadList не дает возможности мне узнать ID потока.
Конечно. Это просто список указателей. Он предназначен именно для манипуляции с ними.
Цитата:
Сообщение от LD-One Посмотреть сообщение
И как мне узнать ID потока в котором был запущен Execute?
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 25.05.2018, 08:33   #10
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,656
По умолчанию

Цитата:
Сообщение от LD-One Посмотреть сообщение
я таким образом пытаюсь хранить имена функций и параметров, самый легкий вариант который я увидел, это забивать в массив под ID потока, потом уже в Execute по ID выполняющегося потока доставать эти данные из ID
Этот вариант - для юных говнокодеров. Сделай по-нормальному:
  1. Выкинь массивы. Все. Забудь про них.
  2. Допиши свой класс от TThread, в котором будут поля и свойства для хранения функцйи и параметров.
  3. Юзай один список TThreadList<твой_потомок_от_TThread >.
  4. Завязывай с веществами и начни пользоваться мозгом.
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...

Последний раз редактировалось min@y™; 25.05.2018 в 08:37.
min@y™ вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

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

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Подпрограммы-процедуры в Delphi. Найти наименьшие положительные элементы и их порядковые номера в массиве emalf Помощь студентам 6 15.12.2016 03:03
запуск потока из таймера, как? buket Общие вопросы Delphi 6 16.12.2011 11:36
[Delphi] Запуск процедуры с параметром ZePr Помощь студентам 10 02.02.2011 16:32
Запуск таймера из потока (delphi 2010) Terikon Общие вопросы Delphi 10 07.08.2010 18:09
Запуск процедуры из процедуры с дополнением 1sal1 Общие вопросы Delphi 3 06.10.2008 21:54