[Delphi] Многопоточность.

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by RedFern.89, 30 Apr 2010.

  1. RedFern.89

    RedFern.89 Member

    Joined:
    20 Jan 2010
    Messages:
    575
    Likes Received:
    48
    Reputations:
    0
    Я знаю. Всех эта тема уже ацки задрала. Но прошу вас о помощи. Гугл и тд не предлагать.. просто помогите. Значит суть такова: например у меня в списке 100 проксей, я хочу проверить весь список скажем в 7 потоков. Желательно, что бы все это дело можно было поставить на паузу, возобновить и прервать вовсе. Я немного разобрался с критическими секциями. Но все это сопоставить немогу. Парни! прошу вас о помощи.. Если вам помощь нужна - я помогу и помогал всегда.. Модераторы - простите засранца за темень в знаниях моих...
     
  2. 1n0y

    1n0y Active Member

    Joined:
    9 May 2009
    Messages:
    276
    Likes Received:
    282
    Reputations:
    2
    пишу код на коленке, думаю разберёшся сам :)

    Code:
    p = class(tthread)
     private
     //переменные
     proxy:striing;
     otver:tstringlist;
      procedure getprx;
      procedure checkprx;
     protected
     procedure execute; override;
    end;
    
    
    var
    form1..
    p1,p2,p3,p4,p5,p6,p7:tthread;
    i:integer;
    pr:bool;
    
    
    //процедура чека проксей
    
    procedure p.checkprx;
    begin
     otver:=tstringlist.create;
     // тут подставляешь прокси в инди(или что там у тебя). прокси - переменная proxy
     try
      otver.text:=http.get(somesite);
      if length(otver)<>0 then // наверное можно только except юзать
       прокси валидный
      else 
       прокси не валидный
     except 
      прокси не валидный
     end;
    end;
    
    
    //создаёшь процедуру, которая будет выдавать каждому потоку проксю
    
    procedure p.getprx;
    begin
     //чтото типо того
     proxy:= form1.memo1.lines[i];
     i:=i+1;
     if i=form1.memo1.lines.count // если прокся последняя - завершать проверку
     then pr:=false;
    end;
    
    procedure p.execute;
    begin
    
    //тутсоздаёшь все компоненты инди, или что там у тебя
    
     Synchronize(getprx); //берёш проксю
     repeat 
       checkprx;   //чекаешь
     until pr=false; 
    end;
    
    
    procedure tform1.button1click(sender: tobject);
    begin
    pr:=true;
    i:=0;
     p1 := tnew.create(true);
     p1.freeonterminate := true;
     p1.priority := tpnormal;
     p1.resume;
    p2 := tnew.create(true);
     p2.freeonterminate := true;
     p2.priority := tpnormal;
    p2.resume;
    // и так до p7
    
    end;
     
  3. агерон

    агерон New Member

    Joined:
    24 Oct 2009
    Messages:
    4
    Likes Received:
    3
    Reputations:
    5
    книга Джона Рихтера 11 глава функция UserWorkItem, делаешь правельные настройки фукции закидываешь все в пул потоков и наслаждаешься жизнью
     
  4. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    Всё очень просто :
    Разберем что есть 100 прокси и 7 потоков.
    Каждый поток должен что делать :
    Брать новый прокси и чекать его, если чекать уже не кого(счётчик равен 100) - поток убиваем. Когда поток убиваем проверяем, последний ли поток убили, если да - то программу информиреум о том что чек закончился.

    Теперь разберем куда всунуть критическую секцию. Во-первых первая критическая секция должна стоять там где берется новый прокси, во-вторых вторая должна стоять где идёт проверка послдений ли поток был убит, получаем вот такой общий код процедуры выполнения потока :
    Code:
    procedure TProxyThread.Execute;
    var cur_id : Cardinal;
    Begin
          repeat
                cs1.Exiter;
                if (pxIndex >= maxProxy) then
                Begin
                      cs1.Leave;
                      Break;
                end;
                cur_id := pxIndex;
                Inc(pxIndex);
                cs1.Leave;
                //Теперь тут мы чекаем прокси с индексом cur_id
                ...
          until Terminated;
          //Тут убираем наш поток из списка активных потоков, проше всего это
          //можно сделать счётчиком убитых потоков и если этот счётчик становится после
          //инкремента равен 7 - значит все потоки остановлены, я проше так и сделаю
          cs2.Enter;
          Inc(termThreads);
          if (termThreads >= 7) then
          Begin
                //Здесь сигнализируем приложению что чек прокси закончился 
          end;
          cs2.Leave;
    end;
    Вот и всё, только переменные перед началом запуска потоков должны быть равны :
    pxIndex := 0;
    ermThreads := 0;

    Что бы на время приостановить чек - выполняем из главного потока : cs1.Exiter; (1)
    Что бы продолжить чек - выполняем из главного потока : cs1.Leave; (2)
    Ток следи что бы (1) и (2) выполнялись симметрично.
     
  5. Meecript_

    Meecript_ Banned

    Joined:
    29 Oct 2008
    Messages:
    194
    Likes Received:
    62
    Reputations:
    32
    Не нужно крит.секций
    Interlocked-функции WinAPI
     
  6. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    В чем профит?