Конференция "Прочее" » Многопоточность и Delphi
 
  • Пробегал2... (25.04.08 15:26) [40]
    Loginov Dmitry ©   (25.04.08 13:40) [37]
    В конце TMyThread.Execute (или в деструкторе) выполняется присвоение MyThread := nil


    о боже. Ты вообще понимаешь что делаешь? Блин, и кто-то говорил о профессионализме... В методах классах обращаться к конкретному экземпляру класса?

    Игорь Шевченко ©   (25.04.08 14:01) [38]
    Тут в ветке где-то про чтение Рихтера говорили. Нафига читать Рихтера, если он в Delphi ни ухом ни рылом ?


    я пожалуй даже отвечать не буду.
  • Loginov Dmitry © (25.04.08 15:29) [41]

    > что является главным признаком фактического завершения исполнения
    > поточной функции.


    Возможно возможно...

    Что же по Вашему является "главным признаком фактического завершения исполнения поточной функции", и как это "что" использовать в данной ситуации?
  • Loginov Dmitry © (25.04.08 15:30) [42]

    > о боже. Ты вообще понимаешь что делаешь? Блин, и кто-то
    > говорил о профессионализме... В методах классах обращаться
    > к конкретному экземпляру класса?


    Вот и объясни мне, как здесь можно выкрутиться без подобных извращений!
  • Сергей М. © (25.04.08 15:45) [43]

    > Loginov Dmitry ©   (25.04.08 15:29) [41]


    Признаком фактического завершения поточной функции является либо вызов ф-ции ExitThread() либо вызов машинструкции RET верхнего уровня вложенности.
  • Пробегал2... (25.04.08 15:59) [44]
    Loginov Dmitry ©   (25.04.08 15:30) [42]
    Вот и объясни мне, как здесь можно выкрутиться без подобных извращений!


    тебе что нужно? Завершить поток? Так сделай ему Terminate, поток должен своевременно проверять Terminated свойство и выходить из Execute когда оно true

    Если ты сделаешь FreeOnTerminate := true - это значит, что после выхода из Execute поток сам вызовет Destroy, то есть такому потоку-классу НЕ НУЖНО делать Free / Destroy.

    Если тебе нужно дождаться завершения работы потока - смотри функции WaitForSingleObject / WaitForMultipleObjects, или уже реализованный метод TThread.WaitFor

    Поэтому если смотреть твой пример [30], то при классе со свойством: FreeOnTerminate := true - правильный сценарий 3.

    При FreeOnTerminate := false правилен такой сценарий:

    MyThread.Terminate;
    MyThread.WaitFor;
    MyThread.Free ;



    Косяк может быть действительно в том, когда вызывается код из секции finalization. Я в библиотеках им не пользуюсь. Используй стандартные посылки Windows. То есть:

    library DllEntry;

    procedure DLLEntryPoint(Reason: DWORD);
    begin
     case Reason:
       Dll_Process_Attach: ДЕЛАЕМ ИНИЦИАЛИЗАЦИЮ БИБЛИОТЕКИ
       DLL_PROCESS_DETACH: ДЕЛАЕМ ФИНАЛИЗАЦИЮ ВСЕХ ДАННЫХ БИБЛИОТЕКИ
     end;
    end;

    // Здесь реализация экспортируемых функций

    // экспорт

    begin
     if DllProc = nil then
     begin
       DllProc := @DLLEntryPoint;
       DllEntryPoint(Dll_Process_Attach);
     end;
    end.

  • Сергей М. © (25.04.08 16:23) [45]

    > Пробегал2


    > Косяк может быть действительно в том, когда вызывается код
    > из секции finalization. Я в библиотеках им не пользуюсь


    Пользоваться или не пользоваться - это твое право.
    Но косяк с дедлоком будет в любом случае.
  • Сергей М. © (25.04.08 16:25) [46]

    > Пробегал2...   (25.04.08 15:59) [44]


    > если смотреть твой пример [30], то при классе со свойством:
    >  FreeOnTerminate := true - правильный сценарий 3


    Неправильный он, как и все остальные сценарии.
  • Пробегал2... (25.04.08 16:33) [47]
    Сергей М. ©   (25.04.08 16:23) [45]
    Но косяк с дедлоком будет в любом случае


    где ты там видишь дедлок?! Словами можешь описать?
  • Loginov Dmitry © (25.04.08 16:35) [48]

    > Признаком фактического завершения поточной функции является
    > либо вызов ф-ции ExitThread() либо вызов машинструкции RET
    > верхнего уровня вложенности.


    Вызов <> признаку!


    > тебе что нужно? Завершить поток? Так сделай ему Terminate,
    >  поток должен своевременно проверять Terminated свойство
    > и выходить из Execute когда оно true
    >
    > Если ты сделаешь FreeOnTerminate := true - это значит, что
    > после выхода из Execute поток сам вызовет Destroy, то есть
    > такому потоку-классу НЕ НУЖНО делать Free / Destroy.
    >
    > Если тебе нужно дождаться завершения работы потока - смотри
    > функции WaitForSingleObject / WaitForMultipleObjects, или
    > уже реализованный метод TThread.WaitFor
    >
    > Поэтому если смотреть твой пример [30], то при классе со
    > свойством: FreeOnTerminate := true - правильный сценарий
    > 3.


    фигня какая-то получается. Я с [0] поста доказываю, что в finalization DLL-библиотеки все это не работает, а вы все-равно внушаете, что так правильно. Да, так правильно! Но не работает!

    Все-таки, я все больше прихожу к выводу, что нужна дополнительная экспортируемая функция. С вариантом, когда Винда при выгрузке DLL срубает потоки еще до finalization, достаточно сложно что-либо другое придумать.
    Ведь такое обращения Windows с потоками - опасно и чревато потерей данных...
  • jack128_ (25.04.08 16:41) [49]

    > Словами можешь описать?

    На меня снижа шло озарение и я понял в чем главная проблема нашего мира.  Мы не слышам друг друга...  

    PS
    [7]
  • Сергей М. © (25.04.08 16:42) [50]

    > Пробегал2...   (25.04.08 16:33) [47]


    см. [7], там как раз объяснение "словами".
  • Сергей М. © (25.04.08 16:53) [51]

    > Loginov Dmitry ©   (25.04.08 16:35) [48]


    > Вызов <> признаку!


    Поправлюсь - не сам вызов, а результат его исполнения.

    В результате исполнения вызова ExitThread или возврата по RET управление будет передано в kernel32 и никогда более не будет передано коду поточной функции, что дает все основания для беспроблемной деаллокации участка ВАП, в котором размещался машкод поточной ф-ции.
  • Сергей М. © (25.04.08 17:04) [52]
    В дополнение к [51] - подразумевается, что код поточной ф-ции м.б. смело удален из ВАП процесса не ранее чем завершат свое выполнение все потоки, созданные ранее с указанием этой поточной функции.
  • Пробегал2... (25.04.08 17:14) [53]
    Loginov Dmitry ©   (25.04.08 16:35) [48]
    Я с [0] поста доказываю, что в finalization DLL-библиотеки все это не работает, а вы все-равно внушаете, что так правильно


    как выяснили, в finalization это действительно не работает. Поэтому не надо этот код писать в finalization. ГДЕ НУЖНО ПИСАТЬ этот код - я написал в посте [44]

    jack128_   (25.04.08 16:41) [49]
    На меня снижа шло озарение и я понял в чем главная проблема нашего мира.  Мы не слышам друг друга...  

    PS
    [7]


    теперь понял! Честное слово, почему-то пропустил пост [7], не читал его... Да, наверное так и есть.
  • Сергей М. © (25.04.08 17:20) [54]

    > Пробегал2...   (25.04.08 17:14) [53]


    > не надо этот код писать в finalization. ГДЕ НУЖНО ПИСАТЬ
    > этот код - я написал в посте [44]


    Финализация юнитов вызвается в контексте вызванной DllMain(DLL_PROCESS_DETACH), так что без разницы, где будет вызвана wait-функция ожидания завершения потока - хоть непосредственно в DllMain, хоть в finalization. Результат будет один и тот же - "не дождетесь !")
  • Loginov Dmitry © (25.04.08 17:29) [55]

    > Финализация юнитов вызвается в контексте вызванной DllMain(DLL_PROCESS_DETACH),
    >  так что без разницы, где будет вызвана wait-функция ожидания
    > завершения потока - хоть непосредственно в DllMain, хоть
    > в finalization. Результат будет один и тот же - "не дождетесь
    > !")


    И это правда!
    Проверено! :)
  • Пробегал2... (25.04.08 17:52) [56]
    Сергей М. ©   (25.04.08 17:20) [54]

    странно... даже как-то бредово... А где же тогда рекомендуется завершать потоки, созданные в DLL? Ведь идеологически при DLL_PROCESS_DETACH самое место...

    Ну тогда я вижу один извращенный вариант, других по-моему просто нет.

    TMyThread = class(TThread)
    private
     FFinallyEvent: Thandle ;
    protected
     procedure execute; override;
     constructor Create;
     destructor Destroy;
     property FinallyEvent: Thandle read FFinallyEvent;
    end;

    ....

    constructor TMyThread.Create;
    begin
     FFinallyEvent := CreateEvent(bla bla не помню что там надо) ;
     FreeOnTerminate := true ;
     ResetEvent(FFinallyEvent);  
     inherited Create(false) ;  
    end;

    destructor TMyThread.Destroy;
    begin
     CloseHandle(FFinallyEvent);
     inherited;
    end;

    procedure TMyThread.Execute;
    begin
     while not terminate
       РАБОТАЕМ
     SetEvent(FFinallyEvent) ;
    end;



    Соответственно, вызовы приблизительно такие:

    var
     MyThread: TMyThread;

    ...

    initialization
     MyThread := TMyThread.Create;
    finalization
     MyThread.Terminate;
     WaitForSingleObject(MyThread.FinallyEvent) ;

    end.



    впрочем, как я понимаю, код с FFinallyEvent можно и убрать. Все равно событие выставляется ДО того, как фактически поток будет завершен, просто максимально приближает ожидания момента к реальному моменту уничтожения потока...

    Так что можно и без event'а... Все равно судя по всему FreeLibary вернет управление, но поток будет продолжать крутиться и ВАП не будет очищено, то есть вс в порядке, в результате все равно все финализируется и беспокоится нечего.

    event можно использовать только как знак, что поток уже на финальной стадии завершения, то есть он уже не будет ничего никуда передавать, не будет ничего создавать и открывать и прочее...
  • Loginov Dmitry © (25.04.08 18:06) [57]

    > Пробегал2...   (25.04.08 17:52) [56]


    Практически тот же изврат, что и при while Assigned(MyThread) do...
    но более правильный.
    От срубания потоков виндой все-равно не спасет! :)
  • Пробегал2... (25.04.08 18:12) [58]
    Loginov Dmitry ©   (25.04.08 18:06) [57]
    Практически тот же изврат, что и при while Assigned(MyThread) do...
    но более правильный


    ну нифига... У тебя все расчитано, что максимум будет создан один поток.. Второй поток уже внесет несусветную суматоху. У меня же поток по всем правилам ООП написан ;) Поменяются тольуо функции ожидания для нескольких потоков, будет использована WaitForMultipleObjects

    Loginov Dmitry ©   (25.04.08 18:06) [57]
    От срубания потоков виндой все-равно не спасет! :)


    да с чего ты взял, что винда потоки срубает?!?! Винда финализирует потоки не при FreeLibrary, а при завершении процесса, тогда она все ресурсы пытается освободить, созданные этим процессом.
  • Игорь Шевченко © (25.04.08 19:05) [59]

    > странно... даже как-то бредово... А где же тогда рекомендуется
    > завершать потоки, созданные в DLL? Ведь идеологически при
    > DLL_PROCESS_DETACH самое место...


    потоки не создаются в DLL. Потоки создаются в процессе. Познай эту истину и будет тебе рулез вечный и немеряный
 
Конференция "Прочее" » Многопоточность и Delphi
Есть новые Нет новых   [134435   +35][b:0][p:0.002]