Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Асинхронные и синхронные потоки, Почему один поток ждет завершения другог 
:(
    Опции темы
petlyura
Дата 21.11.2008, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 162
Регистрация: 30.1.2008
Где: Харьков

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



Привет форумчанам! Есть такая проблема. 
Была прога, в ней создавалось несколько потоков, которые считывали данные с различных COM-портов. Потоки я не синхронизировал, т.к. VCL при этом не задействован.
При этом для выполнения дальнейшего кода надо было подождать, пока все данные с COM-портов не будут считаны.
Вот так вот:
Код
__fastcall
TComThread::TComThread(TShortLLS* shortLLS)
    : TThread(true), ShortLLS(shortLLS)
{
  Priority = tpNormal;    
  FreeOnTerminate = false;
}

void __fastcall
TComThread::Execute()
{
  ShortLLS->ReadLbd(Number, Pointer);
}

int
TShortLLS::Takt()
{
 
 if(countK > 1)
 {
   uint16* p = Oz[countK-1].Cbd.Lbds;
   for (int i=0; i<countK-1; i++)
   {
     ComThread[i] = new TComThread(this);
     ComThread[i]->Pointer = Oz[i].Cbd.Lbds;
     ComThread[i]->Number = i;
   }
   for (int i=0; i<countK-1; i++)
     ComThread[i]->Resume();  // остальные в своих потоках

   ReadLbd(countK-1, p);  // одна задача в основном потоке

   for (int i=0; i<countK-1; i++)
   {
     ComThread[i]->WaitFor();  // ожидаем завершения всех потоков
     ComThread[i]->Free();
     ComThread[i] = NULL;
   }
 }
 else
 {
   if (countK > 0)
   {
     uint16* p = Oz[0].Cbd.Lbds;
     ReadLbd(0, p);
   }
 }
}


Короче, все работало. 
А теперь пришлось добавить код, который выдает сообщение на экран и ожидает, пока пользователь не нажмет OK, чтобы записать время его нажатия. Пока пользователь тупит и смотрит на это сообщения (а их может быть и несколько), необходимо, чтобы дальше выполнялось чтение данных с COM-портов.
Т.к. тут использовалось сообщение, то я закинул его в синхронный поток.
Код
class TMessThread: public TThread
{
  public:
  __fastcall TMessThread():TThread(true){FreeOnTerminate = true;}
  void __fastcall WaitClick();

  AnsiString T;
  AnsiString path;  

  private:
  protected:
     void __fastcall Execute(){Synchronize(WaitClick);}
};

void __fastcall TMessThread::WaitClick()
 {
    if (Application->MessageBox(T.c_str(), "Бла-бла", MB_ICONINFORMATION|MB_OK) == IDOK)
    {
      AnsiString M = "фвы: "+T;
      TUstCmd cmd("TDtDsCmd", M.c_str(), "-", "-");
      PutUserCmd(path.c_str(),idasut.c_str(),cmd);
    }
}

void TCl::Function()
{
//.......................
    thr = new TMessThread();
    thr->T = Text1;
    thr->path = Path;
    thr->Resume();
//.......................
}


А теперь трабла: После завершения WaitClick, ну и, соответственно, TMessThread::Execute, следующий шаг (нажимаю F7), идет 
ComThread[i]->Free();
ComThread[i] = NULL;
Как будто ComThread дождался WaitFor своего. При этом ComThread[i] уже ссылается на другую область памяти (другой адрес), а следующий ComThread[i] вообще равен NULL, и выбрасывает на ComThread[i]->WaitFor(); Access Violation at address ... Read of address. (что и понятно, ведь ComThread[i] = NULL). 
Почему после выполнения TMessThread::Execute происходит потеря памяти у ComThread, и что делать?

Пробовал для MessThread, FreeOnTerminate = false; и WaitFor, но все равно трабла.
PM MAIL   Вверх
dumb
Дата 22.11.2008, 04:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


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

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



Цитата(petlyura @  21.11.2008,  14:57 Найти цитируемый пост)
     void __fastcall Execute(){Synchronize(WaitClick);}
такой код практически всегда является следствием недопонимания происходящего.

если ReadLbd работает с COM-портом, и к тому же уже сделана обертка для вызова этой функции из отдельных потоков, то оставлять один ее вызов в основном потоке как-то неразумно.

Цитата(petlyura @  21.11.2008,  14:57 Найти цитируемый пост)
ComThread[i]->Free();
в курсе, что есть такая клевая штука, как deletesmile

а в общем, без полного кода тут довольно трудно что-то сказать наверняка, а полный код, судя по всему, довольно объемен и запутан, так что я на твоем месте рассчитывал бы в основном на свои силы.
PM MAIL   Вверх
petlyura
Дата 22.11.2008, 12:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 162
Регистрация: 30.1.2008
Где: Харьков

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



Все ок! Синхронайз убрал, на всяк пожарный применил ф-цию 
int MessageBox(
    HWND hWnd,    // handle of owner window
    LPCTSTR lpText,    // address of text in message box
    LPCTSTR lpCaption,    // address of title of message box  
    UINT uType    // style of message box
   );    
вместо VCL TApplication::MessageBox.
Работает. Тьфу-тьфу-тьфу!
Всем спасибо за участие!
  
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

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

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

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

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


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

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


 




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


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

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