Конференция "Сети" » два потока. события, синхронизация [D7, WinXP]
 
  • Жека (01.11.07 20:28) [0]
    пишу компонент реализующий протокол взаимодействия с сервером. при подключении компонент создает ещё один поток в котором принимает команды от сервера. при получении команды поток вызывает Synchronize(parse). в методе parse происходит обработка команды и вызов соответствующих обработчиков событий. все бы ничего за вот понадобилось в компоненте реализовать функцию которая бы отправляла на сервер некоторый запрос и возврашала управление ->
  • Жека (01.11.07 20:35) [1]
    только при получении ответа от сервера на этот запрос. я попробовал реализовать эту схему используя event  и waitforsingleobject но так как парсинг происходит в главном потоке программа зависает. есть ли варианты решения этой ситуации. заранее пасипа! :)
  • DVM © (01.11.07 23:48) [2]
    Странное желание. Ты, пытаясь избавиться от блокировки основного потока сетевыми функциями, создаешь доп поток и потом хочешь обратно получить блокировку. Получив эту блокировку - ты жалуешься что программа зависает :) Ты уж реши что тебе важнее.
  • Жека (02.11.07 07:09) [3]

    > Странное желание. Ты, пытаясь избавиться от блокировки основного
    > потока сетевыми функциями, создаешь доп поток и потом хочешь
    > обратно получить блокировку. Получив эту блокировку - ты
    > жалуешься что программа зависает :) Ты уж реши что тебе
    > важнее.

    Компонент действительно должен иметь возможность блокирующих и неблокирущих вызовов сетевых функций. Но так как используется отдельный поток для чтения команд, я не могу использовать SendCmd. В результате планирую получить что-то вроде: function TMegaComponent.SendPacket(Cmd: string; Params: array of string; Blocked: Boolean{если да то поток замораживается до прихода ответа}): TCmd;

    P.S. Утром пришла идея делать проверку в слушающем потоке перед передачей упревления в Synchronize:

    if MainThread.IsSleeped then
    begin
     if RecvedCmd = WaitedCmd then
     begin
       SetEvent(Event);
       while Buffer.Count > 0 do
       begin
         Cmd := Buffer[0];
         Synchronize(Parse);
       end;
     end else
     begin
       AddToBuffer(Cmd);
     end;
    end else
    begin
     Synchronize(Parse);
    end;

    Можт в чёт-то ошибся, но общая идея такая
  • Reindeer Moss Eater © (02.11.07 09:16) [4]
    А зачем парсить-то в главном? В главнный поток надо посылать уже готовые команды и события.
  • Anatoly Podgoretsky © (02.11.07 09:25) [5]
    И это не надо, в главном потоке делать только отрисовку и если более одного потока и они нуждаются в синхронизации, то события синхронизации.
  • Жека (02.11.07 12:52) [6]

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

    Т.е.? я ведь не могу вызывать обработчики событий прямо из слушающего потока, т.к. в них может быть потоконебезопасный код. Или я неправильно вас понял.

    > И это не надо, в главном потоке делать только отрисовку
    > и если более одного потока и они нуждаются в синхронизации,
    >  то события синхронизации.

    У меня только один поток, я просто не могу понять как мне вызвать обработчики событий так, чтобы непроизошло конфликтов. А вообще я взял за основу исходник компонента TIRQ у него это реализованно именно так (весь парсинг происходит в VCL-потоке)
  • Anatoly Podgoretsky © (02.11.07 13:15) [7]
    > Жека  (02.11.2007 12:52:06)  [6]

    А у Арханлеьского вся обработка вообще проходит в основном потоке и что? Разве это примеры для подражания.
  • Жека (02.11.07 13:31) [8]

    > Anatoly Podgoretsky ©   (02.11.07 13:15) [7]

    Но какие минусы в этой системе, это ведь не серверная часть, в которой распаралеливание действительно может дать прирост производительности и сделать программу более стабильной. Слушающий поток создан только для того чтобы интерфейс не замораживался. Если действительно существуют весомые причины для того, чтобы парсинг производить в отдельном потоке, то как мне вызывать обработчики событий? каждый раз сохранять параметы обработчика в переменных потока после чего вызывать Synchronize(OnCmd1) ? мне кажется это излишняя громоздкость. или я ошибаюсь?
  • Anatoly Podgoretsky © (02.11.07 14:11) [9]
    Размораживание интерфейса надо делать через Application.ProcessMessages, а при работе с сетью использовать ассинхронные методы работы. Потоки не для того.
  • Жека (02.11.07 14:57) [10]
    Я уже написал значительную часть проекта используя Indy, там не предусмотрена асинхронность
  • Anatoly Podgoretsky © (02.11.07 15:10) [11]
    > Жека  (02.11.2007 14:57:10)  [10]

    Знаешь я написал целый проект, но это не остановило меня от перехода на ICS
  • Жека (02.11.07 15:34) [12]
    Чтожь, видно меня ждёт море работы, спасибо за совет.
  • MetalFan © (05.11.07 11:47) [13]

    > Потоки не для того.

    а для чего? прекрасно можно и индейцев в поток запихать)
  • Anatoly Podgoretsky © (05.11.07 11:58) [14]
    автор> Слушающий поток создан только для того чтобы интерфейс не замораживался.

    АП> Размораживание интерфейса надо делать через Application.ProcessMessages

    Потоки созданы не для размораживания интерфейса, а для паралельного исполнения задач. Хотя любой микроскоп можно использовать и не по назначению, но это говорит об отсутствии должной квалификации.
 
Конференция "Сети" » два потока. события, синхронизация [D7, WinXP]
Есть новые Нет новых   [134431   +10][b:0][p:0]