Подвисание потоков

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by Protocoler, 16 Mar 2018.

  1. Protocoler

    Protocoler Elder - Старейшина

    Joined:
    10 Oct 2012
    Messages:
    51
    Likes Received:
    54
    Reputations:
    81
    В дополнение к вопросу о "Обращении к экземплярам класса потока":

    Проблема :
    При остановке потоков почти каждый раз подвисает разное количество потоков. Завершение потока происходит
    присвоению переменной work знач. false .

    Схема остановки потока:
    Code:
    potok.Execute;
    begin
    
    while work=true do
    begin
    working_threads[number]:=''; // Отслеживание действий. см. ниже
    end;
    
    if work=false then
    begin
      terminate;
    end;
    
    end;


    Как я отслеживаю где зависает поток :
    При указании размера массива потоков я создаю дубль этого массива только String значений ( в примере : working_threads ). working_threads находится в глобальном VAR , т.е. в var главного потока.
    Потом внутри каждого потока запоминаю номер потока. Так как потоки создаются по очереди из главного потока, я просто сделал так :
    Code:
    potok.Execute;
    begin
     critical.Enter;
     number:=f_thread; // Запоминаем номер потока
     inc(f_thread);  // где f_thread : integer;
     critical.Leave;
    
    


    И по мере прохождения кода меняю содержимое ячейки массива соответсвующего номеру потока.
    Пример :
    Code:
     potok.Execute;
    begin
    
     critical.Enter;
     number:=f_thread; // Запоминаем номер потока
     inc(f_thread);  // где f_thread : integer;
     critical.Leave;
    
    while work=true do
    begin
    working_threads[number]:='start';
    .....
    .....
    working_threads[number]:='part2';
    .....
    .....
    working_threads[number]:='part3';
    end;
    
    
    
    if work=false then
    begin
    working_threads[number]:='thread finished';
      terminate;
    end;
    
    end;
    
    
    Вопрос №1 :

    Я изменяю содержимое этого массива без критической секции , так как каждый поток меняет только свою ячейку. Я прав ? Или
    в любом случае при обращении к одному и тому же массиву ( не ячейке ) нужно применять критич. секцию ?

    У меня вроде норм все отрабатывает.


    Вопрос №2 :

    В одном из кусков кода я считываю значения из Ini файла. Только считываю ( только ). Заметил что какие-то потоки подвисают на этом деле.
    Вопрос такойже как предыдущий.. Можно так делать или стоит применять критич. секцию ? ( я же только считываю значения )...


    Вопрос №3 : Бывает потоки подвисают на part3 и не доходят до thread finished, хотя их выполнение уже в конце цикла while..
    Какого черта собственно ?



    Объясните пожалуйста. Заранее благодарствую.
     
    #1 Protocoler, 16 Mar 2018
    Last edited: 16 Mar 2018
  2. Protocoler

    Protocoler Elder - Старейшина

    Joined:
    10 Oct 2012
    Messages:
    51
    Likes Received:
    54
    Reputations:
    81
    Ладно, продолжу тему сам..

    Используя Synapse ,
    При завершении потока через Thread.Free получаю зависания на этой процедуре...

    Кусок кода в котором происходит зависание :

    Code:
    try
        thread[r].POP.Sock.AbortSocket;
        thread[r].IMAP.Sock.AbortSocket;
        finally
    showmessage('1');
        thread[r].Free;
    showmessage('2');
        end;
    Этот Код работает в отдельном потоке, и принадлежит другому классу. В потоках которые завершаются идет работа с Сокетами, может в этом проблема ?

    1 - 2 потока могут завершиться нормально, с промежутком уведомления об этом через showmessage примерно в 4-7 секунд.. Но дальше, просто все подвисает.. И Showmessage('2') я никогда не увижу..

    Подскажите в чем может быть проблема и как ее решить ?

    P.S. Дело не в synchronize )) Проверяющий поток - 1 .
     
  3. #colorblind

    #colorblind Moderator

    Joined:
    31 Jan 2014
    Messages:
    637
    Likes Received:
    246
    Reputations:
    42
    Проблема в некорректном завершении потока.
    PHP:
      thread[r].Terminate;
      
    thread[r].WaitFor;
      
    thread[r].Free
     
  4. Protocoler

    Protocoler Elder - Старейшина

    Joined:
    10 Oct 2012
    Messages:
    51
    Likes Received:
    54
    Reputations:
    81
    Я не просто так делаю сразу Free . Ибо в Синапсе юзаются блокирующие сокеты, и при зависании самого сокета, thread[r].Terminate и WaitFor Никогда не наступает.. В моем случае никакие таймауты не помогают, ибо зависает сам сокет, по этому пытаюсь убить зависший поток из друго-го потока.. Но снова же получаю зависание на .Free

    Как быть ?
     
    #4 Protocoler, 14 May 2018
    Last edited: 14 May 2018
  5. #colorblind

    #colorblind Moderator

    Joined:
    31 Jan 2014
    Messages:
    637
    Likes Received:
    246
    Reputations:
    42
    Попробуй TerminateThread(thread[r].Handle, $DEADC0DE);
     
  6. #colorblind

    #colorblind Moderator

    Joined:
    31 Jan 2014
    Messages:
    637
    Likes Received:
    246
    Reputations:
    42
    А вообще не плохо было бы запихать прогу в отладчик и посмотреть, в чем проблема. Гадать на кофейной гуще можно очень долго