Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблемы при работе с несколькими потоками, Многопоточное приложение 
V
    Опции темы
witeman
Дата 2.8.2006, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 29.3.2005
Где: г.Тюмень

Репутация: нет
Всего: нет



  Здравствуйте, как вы уже наверное догадались в данной теме речь пойдёт о многопотчном приложении. Перед тем как я сформулирую ошибку, я опишу вам структуру своего проекта. Вообще сейчас я пишу программу для пересылки файлов в сети будь-то телефонное соединение или же локальная сеть. На сервере выбирается файл для отправки и отправляются клиенту поток связанный с выбраннным файлом, а клиент соответственно его принимает. Сначало о принципах работы... Клиент и сервер обмениваютсяпсевдо-командами,например: при выборе файла на сервере 
выполняется следующий код:
Код

if(Dialog->Execute() && Dialog->FileName!="")
 {
    FileName=Dialog->FileName;
    MessageDlg("Файл подготовлен к передаче:\n"+FileName,mtInformation, TMsgDlgButtons() << mbOK, 0);
    RzExpandEdit1->Font->Color=clBlack;
    RzExpandEdit1->Text="Файл \""+FileName+"\" готов к передаче";
    RzExpandEdit1->Visible=true;
    RzProgressBar2->Percent=0;
    RzProgressBar2->Visible=true;
    Selected=true;
 }
 
 else
 {
    SelFile=false;
 }

 if(ServerSocket1->Socket->ActiveConnections!=0&&SelFile!=false)
 {
    ServerSocket1->Socket->Connections[0]->SendText("!selected");
    return;
 }
 else
 {
    if(SelFile==false)
    {    
            SelFile=true;
    } 
 }


А когда подключается клиент такой код:
Код

 RzStatusPane1->Caption="Присоединился: "+Socket->RemoteHost;
 if(SelFile==true)
  {
    ServerSocket1->Socket->Connections[0]->SendText("!selected");
    return;
  } 

т.е. я имею ввиду строку "!selected", котроая посылается клиенту и, вследствие этого, на клиентском 
выполняется обработчик события - проверяется какая команда была послана, выполняется соответсвующее действие  
ну и т.п.   

Ниже я привел обработчик события сокета сервера(для чего я все это делаю будет понятно дальше) :
Код

s = Socket->ReceiveText();

 if (s=="!send")
 {
    if(FileName!="")
    {
    ms = new TFileStream(FileName,fmOpenRead);
    RzProgressBar2->Percent=0;
    ms->Position = 0;
    Socket->SendText(IntToStr(ms->Size)+';'+FileName);
        }
 }
 
 if (s=="!ready")
 {
      try
         {
        g=new PercentH(false);
        RzExpandEdit1->Font->Color=clOlive;
        RzExpandEdit1->Text="Подождите, не закрывайте приложение (идёт передача файла)";
        ServerSocket1->Socket->Connections[0]->SendStream(ms);   
     }

      catch ( ... )

     {
        ShowMessage("!");
     }
 }
 
 if (s=="!ok")
 {
    g->Terminate();
    RzProgressBar2->Percent=100;
 }

 if(s=="!error")
 {
    RzExpandEdit1->Font->Color=clBlack;
    RzExpandEdit1->Text="";
    Application->MessageBox("Ошибка передачи данных клиенту\n (попробуйте передать файл ещёраз).","Ошибка",MB_ICONERROR+MB_OK);
    RzExpandEdit1->Visible=false;
    RzProgressBar2->Visible=false;
    delete ms;
 }


"ms" - это объект класса TFileStream (его я объявил в ".h")
  Во время закачки у клиента отображаются проценты (Это вычисляеися простейшим арифмитическим методом пропорции: RzProgressBar1->Percent=100*Data->Size/DataSize : где Data - объект класса TFileStream, а его свойство означает сколько 
процентов закачено, т.е. размер файла в которого записывает поток;DataSize - размер пересылаемого файла )
А по поводу сервера я долго ломал голову как можно реализовать подчет процентов, ведь когда сокет начинает посылку потока
"код блокируется". Тут мне в голову пришла идея о многопоточности. Прочитав пару раз главу из книги, я начал написать второй поток.
Код

void __fastcall PercentH::Execute()
{
  HANDLE Mutexofallsystems;
  Mutexofallsystems=CreateMutex(NULL,false,Form1->RzProgressBar2->Name.c_str());
   while(true)
   {
        if(WaitForSingleObject(Mutexofallsystems,INFINITE)==WAIT_OBJECT_0)
    {
             Synchronize(Display);
             Form1->RzProgressBar2->Refresh();
             
         if(Form1->RzProgressBar2->Percent==99)
             {
                Form1->RzProgressBar2->Percent=100;
        Form1->RzExpandEdit1->Font->Color=clGreen;
        Form1->RzExpandEdit1->Text="Файл \""+Form1->Dialog->FileName+"\" успешно передан клиенту";
        break;
         }
        }
    ReleaseMutex(Mutexofallsystems);
   }
}
//---------------------------------------------------------------------------
void __fastcall PercentH::Display()
{
    Form1->RzProgressBar2->Percent=Form1->ms->Position*100/Form1->ms->Size;
}



Все как и положено, доступ к визуальному компоненту предоставлен через Mutex и Synchronize, и код вроде бы правильный, да и что самое главное 
работает, если бы не одно НО! Как мы видим в функции-члене Display(), идёт обращение к другому потоку , о котором я говороил ранее 
(см.обработчик события сокета сервера), именно из-за этого и возникает ошибка. А конкретнее ошибке возникет из-за взаимодействия ServerSocket1->Socket->Connections[0]->SendStream(ms) и метода Synchronize. Как я пологаю во время того как один поток (я имею ввиду поток сокета)
прекратил свое существование другой продолжает ссылаться на него, и использовать его данные. Все вроде-бы логично , но всё же Display() использует в 
вычисления поток ms, который ни какого отношения (не считая использования) к потоку сокета не имеет! Что же все-таки в итоге получается? Что два 
потока используют ms и, из-за синхронного обращения возникет ошибка!?
  Эта ошибка чаще всего появляется под конец закчки т.е. стабильно на 99%. Но это ещё не все... Иногда бывает так что посередине зкачки отлдчик выдаёт мне 
сообщение об ошибке, но уже иного плана "Can't canvas drawing" или что-то в этом роде (у меня нет возможности сейчас это проверить),но т.к. я использовал 
вовсе не канву, а визуальный компонент, причем предаставил доступ к нему правильным образом, меня это подталкивает к выводу, что ошибка всё таже....
Ну вот я и озвучил все проблемы и вопросы, которые у меня были. Готов принять практически любые предложения вплоть до модификации соката или потока; Если у
кого-нибудь есть идеи как реализовать данную задачу, и вовсе без второго потока, я с радостью выслушаю предложения. Заранее благодарен. smile




PM MAIL WWW   Вверх
witeman
Дата 4.8.2006, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 29.3.2005
Где: г.Тюмень

Репутация: нет
Всего: нет



Товарищи, неужели ни у кого нет ни каких идей!?  smile  Обидно... 
PM MAIL WWW   Вверх
_hunter
Дата 4.8.2006, 10:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 24
Всего: 98



идеи у кого-то может и есть (точнее могли бы появится при правильном вопросе), но тут много текста ни о чем. так же радуют сообщения об ошибках (точнее полное отсутсвие оного в первом случае и непонятный набор слов во втором)
поэтому ограничусь стандартными советами:
1 (самый главный) -- если не можеш найти ошибку -- упрощай задачу
2 -- перед работой с указателем проверяй его валидность
3 -- проверь синхронизацию


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
witeman
Дата 4.8.2006, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 29.3.2005
Где: г.Тюмень

Репутация: нет
Всего: нет



Цитата

но тут много текста ни о чем
 
Ага так значит  smile .
Цитата

перед работой с указателем проверяй его валидность

Ну это то безусловно...
А по поводу
Цитата

проверь синхронизацию
 
В этом собственно и весь вопрос. Как? здесь мне и нужен ваш совет,ведь я же уже и так использую Mutex,  да + тут 3 потока.
P.S.По поводу раздутости текста ты _hunter, отчасти прав, но мне, просто так легче сформулировать проблему,
да и не будет всяких вопросов по поводу раелизации потока smile 
PM MAIL WWW   Вверх
Romikgy
Дата 4.8.2006, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 11
Всего: 146



Я единственого не понял , как ты создаешь потоки????
Виндовыми функциями или билдера? 
если виндовыми то и создавай/следи за синхронизацией, если же билдаром поток создан , на кой те в мутексы лезть , создай функцию и вызови 
Цитата(witeman @  2.8.2006,  11:37 Найти цитируемый пост)
Synchronize


чего мудришь не понятно?

Добавлено @ 11:44 
Если хоть чуть чуть разбираешься в дельфи , то прочти это, очень пользительно
http://forum.vingrad.ru/index.php?showtopic=60076


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
witeman
Дата 4.8.2006, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 29.3.2005
Где: г.Тюмень

Репутация: нет
Всего: нет



Romikgy, это я уже сам запутался, Mutex здесь совсем не нужен smile - Synchronize то уже есть.
 
Цитата

Виндовыми функциями или билдера? 
Создаю поток средствами билдера.
Но тем не менее ошибка та же остается...
А за статью огоромное спасибо - просто супер smile 

PM MAIL WWW   Вверх
Romikgy
Дата 4.8.2006, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 11
Всего: 146



Цитата(witeman @  4.8.2006,  11:13 Найти цитируемый пост)
А за статью огоромное спасибо

не мне а автору статьи!
еще раз об ошибке , и плз без воды, конкретно


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
dumb
Дата 4.8.2006, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 32
Всего: 158



Цитата(witeman @  4.8.2006,  12:13 Найти цитируемый пост)
Но тем не менее ошибка та же остается...

все обращения к компонентам vcl должны быть внутри вызываемой Synchronize процедуры.
PM MAIL   Вверх
witeman
Дата 4.8.2006, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 29.3.2005
Где: г.Тюмень

Репутация: нет
Всего: нет



В конец расстроенный гонениями типа: 
Цитата
много текста ни о чем
Цитата
набор слов 
Цитата
если не можеш найти ошибку -- упрощай задачу
 
(Блин я же это всё писал для того чтобы была понятна не только сама проблема,но ещё и все ньюансы smile !)
Я погрузился в раздумья над своим сырцом. В конце концов понял в чем ошибка! smile Модифицировал методы создоваемого потока и вот что получилось:
Код

void __fastcall PercentH::Execute()
{
        FreeOnTerminate=true;
                while(!Terminated)
                {
                        Synchronize(DisplayPercent);
                        Form1->RzProgressBar2->Refresh();
                        Application->ProcessMessages();
                }
}
//---------------------------------------------------------------------------
void __fastcall PercentH::DisplayPercent()
{
        try
        {
                Form1->RzProgressBar2->Percent=Form1->ms->Position*100/Form1->ms->Size;
        }        
        catch(...)        
        {
                Terminate();
                Form1->RzProgressBar2->Percent=100;
                Form1->RzExpandEdit1->Font->Color=clGreen;
                Form1->RzExpandEdit1->Text="Файл \""+Form1->Dialog->FileName+"\" успешно передан клиенту";

        }
}

Я вставил блоки и сключения и !самое главноне! в catch(...) указал функцию выхода из потока Terminate(). Всё ошибка решена. Занавес... smile 
Всем спасибо за проявленный интерес к вопросу! smile 
З.Ы.:Romikgy
Цитата

не мне а автору статьи!  
и вам тоже smile .

PM MAIL WWW   Вверх
_hunter
Дата 4.8.2006, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 24
Всего: 98



дык это не решение проблемы. это ее извращенное убийство...
это как вырезать кусок стены чтобы прохладнее стало вместо того, чтобы открыть окно...

по проблеме:
у тебя есть цепочка потенциально невалидных указателей:
Form1, RzProgressBar2, Percent, ms, Position, Size;
ни один из них ты не проверяеш...


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
Romikgy
Дата 4.8.2006, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 11
Всего: 146



Цитата(witeman @  4.8.2006,  13:34 Найти цитируемый пост)
 Application->ProcessMessages();

на кой это в потоке?

Добавлено @ 15:12 
Цитата(witeman @  4.8.2006,  13:34 Найти цитируемый пост)
и вам тоже

тогда пжалста , был рад помочь smile


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0837 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.