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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 08.01.2013, 18:51   #1
Pcrepair
Форумчанин
 
Регистрация: 04.01.2011
Сообщений: 260
По умолчанию Как правильно из потока менять Переменные в другом потоке?

Добрый день. Есть следующий код потока

Код:
Procedure TStartTHreadLoader.BeginLoadTHreads(const Urls:string);
var
T:TStringList;
Indx1,Indx2:integer;
UrlStr:string; (*Перем для хранения УРЛ при передаче в СТЕК*)
Url:string; (*строка = УРЛ из массива*)
NumOfTHreads:integer; (*число строк с УРЛ переданное из МЕМО*)
UrlStack:TStack<String>; (*объявляем строковый СТЕК*)
begin
  T:=TStringList.Create;
  T.Text:=Urls;
    (*------------ВОПРОС1---------------------*)
      CS.Enter;  (*вход в КС*)
         try
         (*инициализация ГлобПЕрем перед циклом.
         сделать как метод класса?*)
            CurrentNumOfTHreads:=0;
         finally
            Cs.Leave;  (*выход из КС*)
         end;
   (*----------------------------------*)
   NumOfTHreads:=T.Count;

   (*---ВОПРОС2 вот тут очень криво, обращение к компонентам основной формы*)
     CS.Enter;
        try
        (*сделать вызов метода метода класса?*)
           Form1.Label2.Caption:=IntToStr(NumOfTHreads);
        finally
           Cs.Leave;
        end;
   (*---------------------------------------------------------------*)
   
     UrlStack:=TStack<String>.Create(); (*создаем СТЕК типа строка*)
      (*---ЦИКЛ ввода строк УРЛ в СТЕК-----*)
       for Indx1 := 0 to T.Count-1 do
          begin
           UrlStr:=T[Indx1];
           UrlStack.Push(UrlStr);
          end;
       (*----------------------------------*)
       (*----ЦИКЛ запуска потоков через УРЛ из СТЕК*)
       while (UrlStack.Count <> 0) do
        (*------------------------------------*)
        for Indx2 := 0 to UrlStack.Count-1 do
          begin
            if (10 > CurrentNumOfTHreads) then
              
              (*----------Вопрос 3----------------*)
              begin
                CS.Enter;
                  try
                    Inc(CurrentNumOfTHreads, 1); (*увеличиваем на +1*)
                  finally
                    Cs.Leave;
                  end;
              (*-------------------------*)
              
                if UrlStack.Count <> 0 then
                Url:=UrlStack.Pop;
                StartLoadTHread(Url); (*вызов процедуры запуска потока закачки страницы*)
                Sleep(10); (*интервал между запусками потоков*)
              end
              else Sleep(5); (*обязательно, иначе процессор вход в перегрузку*)
             (*---------------------------*)
        end;
       (*-----------------------------------------*)
   FreeAndNil(UrlStack);
   FreeAndNil(T);
end;
Внимание!!! Вопросы:
код помеченный как ВОПРОС1...3 через КС обращается к основному потоку. в случае обращения к объекту в основном потоке надо делать процедуру как метод класса. а в данном случае надо ли делать метод класса из обращения к ГП типа СТРОКА и к ЛЕЙБЛ на основной форме?
Pcrepair вне форума Ответить с цитированием
Старый 09.01.2013, 10:33   #2
3D Hunter
Сумрачная тень
Форумчанин
 
Аватар для 3D Hunter
 
Регистрация: 05.03.2009
Сообщений: 689
По умолчанию

создавать отдельный метод для обращения к глобальным переменным не требуется.а вот то,что бы обращаетесь к свойствам визуальных компонентов через поток,это неверно.там,где идет обращение к компонентам,этот код выносится в отдельный метод потока и вызывается в вашей процедуре через synchronize()
"ковыряю изнутри" (с)
3D Hunter вне форума Ответить с цитированием
Старый 09.01.2013, 17:42   #3
Pcrepair
Форумчанин
 
Регистрация: 04.01.2011
Сообщений: 260
По умолчанию

3D Hunter, спасибо за подсказку, но:

а если глоб перем представляет собой объект, в частности СТЕК из Дженерик.
тут как раз косяк был, когда через КС из потока вызывал метод этого класса(СТЕК.вставить).
когда переделал вызов в отдельную процедуру в составе которой были КС, косяк полностьб пропал
Pcrepair вне форума Ответить с цитированием
Старый 10.01.2013, 05:33   #4
3D Hunter
Сумрачная тень
Форумчанин
 
Аватар для 3D Hunter
 
Регистрация: 05.03.2009
Сообщений: 689
По умолчанию

сделайте критическую секцию внутренней приватной переменой вашего класса-дженерика и в методе вставки используйте вхождение и выход из нее.это не только абстрагирует логику класса,но и избавит от необходимости помнить,где мы входили или выходили из секции.кроме того,использование классом своей секции в методах ускоряет работу в вашем случае,ибо эта секция используется внутри класса,а для глобальных нужд создается другая секция.старайтесь писать классы сразу потокобезопасными,если они будут использоваться более чем одним потоком.
"ковыряю изнутри" (с)
3D Hunter вне форума Ответить с цитированием
Старый 10.01.2013, 14:11   #5
Pcrepair
Форумчанин
 
Регистрация: 04.01.2011
Сообщений: 260
По умолчанию

и все таки не понятно. вот у меня есть ГлобПерем СТЕК
Код:
unit uGlobalVar;
interface
uses Classes, SysUtils, SyncObjs, Generics.Collections;
var
CS:TCriticalSection; (*используем КС для передачи результата в основной поток*)
gRestartLoadUrls:TStack<String>; (*объявляем строковый СТЕК для незакачанных УРЛ*)
implementation

initialization
   Cs:=TCriticalSection.Create;
   gRestartLoadUrls:=TStack<String>.Create(); (*создаем СТЕК типа строка*)
   gRestartLoadUrls.Clear(); (*удаляем все строки на всякий случай*)
finalization
  FreeAndNil(CS);
  FreeAndNil(gRestartLoadUrls);
end.
в которую через КС потоки через gRestartLoadUrls.Add пишут свои строковые данные
по окончании цикла работы, строки накопившиеся в СТЕК потом обрабатываются в потоке, доступ опять через КС и gRestartLoadUrls.Pop

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

написать процедуру с использованием СТЕК? в которой использовать КС?
желательно пример, что то о таком вообще не читал
Pcrepair вне форума Ответить с цитированием
Старый 11.01.2013, 11:21   #6
3D Hunter
Сумрачная тень
Форумчанин
 
Аватар для 3D Hunter
 
Регистрация: 05.03.2009
Сообщений: 689
По умолчанию

type
tstack=class
protected
fRTL=trtlcriticalsection;
public
procedure add();
...
Procedure add();
begin
try
ENTERCRITICALSECTION(fRTL);
<<ТУТ ВАШ КОД>>
FINALLY
leavecriticalsection(fRTL);
end;
end;
"ковыряю изнутри" (с)
3D Hunter вне форума Ответить с цитированием
Старый 11.01.2013, 11:22   #7
3D Hunter
Сумрачная тень
Форумчанин
 
Аватар для 3D Hunter
 
Регистрация: 05.03.2009
Сообщений: 689
По умолчанию

критическую секцию сделайте классовой переменной.вот о чем хотел сказать.возможны ошибки,сейчас в армии и с телефона не очень удобно
"ковыряю изнутри" (с)
3D Hunter вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Доступ или создание объекта в другом потоке Maks1978 Общие вопросы C/C++ 0 04.10.2012 13:51
Как приостаносить поток до события в другом потоке Sionus Помощь студентам 2 30.03.2010 21:51
Как правильно делать запрос к mysql находящейся на другом сервере Sarumjan PHP 1 27.02.2010 22:39
Как правильно Менять текстовые значения Аннотаций в Солиде Stilet Общие вопросы Delphi 0 21.01.2009 16:51
Как правильно использовать переменные в процедурах nikolai_P Microsoft Office Excel 22 15.05.2008 13:15