Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с синхронизацией 
:(
    Опции темы
NiJazz
  Дата 2.11.2004, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Jazz coder
****


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

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



У меня такая ситуация. Есть два приложения: сервер и клиент. Общаются по Named Pipe. Когда клиент готов к отправке данных, он вызывает SetEvent и сервер переходит к вызову CreateNamedPipe. Сервер работает постоянно. Основная загвоздка заключается в том, что нужно, чтобы пока от клиента нет событий, то есть пока сервер ждёт, он выполнял какое-то действие, например, постоянно что-то писал в файл. Как только событие возникает, сервер прекращает работать с файлом и переходит к "общению" с клиентом.
Я так понял, что когда клиент умолкает, сервер запускает функцию, в которой в бесконечном цикле идёт работа с файлом. Но как остановить эту функцию?
Здесь помогут функции CreateThread и TerminateThread?
Спасибо.
PM MAIL   Вверх
Step
Дата 2.11.2004, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



поставьте в цикл WaitForSingleObject с пердварительной инвертацией

т.е. что бы она переходила в режим ожидания когда событие есть а не наоборот


--------------------
- Дурак учится на своих ошибках, умный на чужих.
 - умные учатся у дураков
PM MAIL ICQ   Вверх
NiJazz
Дата 2.11.2004, 19:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Jazz coder
****


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

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



Step
Цитата
с пердварительной инвертацией

Это как сделать? :qstn
То есть чтобы программа не висела при вызове WaitForSingleObject?
PM MAIL   Вверх
Mad
Дата 3.11.2004, 11:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

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



NiJazz
Можно вызывать WaitForSingleObject с таймаутом 0, тогда он будет просто проверять установлен ли эвент.

Но правильней будет через потоки.



--------------------
user posted image
PM MAIL   Вверх
bel_nikita
Дата 4.11.2004, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

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



Цитата
Я так понял, что когда клиент умолкает, сервер запускает функцию, в которой в бесконечном цикле идёт работа с файлом. Но как остановить эту функцию?

Может стоит два треда организовать.

Вот, абстракция такая залетела в голову:

класс потока
Код

 class Thread
 {
 public:
   Thread ( DWORD (WINAPI * pFun) (void* arg), void* pArg)
   {
     _handle = CreateThread (0,
                             0,
                             pFun,
                             pArg,
                             CREATE_SUSPENDED,
                             &_tid);
   }

   ~Thread () { CloseHandle (_handle); }
   void SetPriority(int nPriority){SetThreadPriority(_handle,nPriority);}
   void Resume () { ResumeThread (_handle); }
   void Suspend() { SuspendThread(_handle); }
   void WaitForDeath ()
   {
     WaitForSingleObject (_handle, 2000);
   }
   HANDLE GetHandle() { return _handle; }
 private:
   HANDLE _handle;
   DWORD  _tid;     // thread id
 };

абстрактный класс двух активных потоков:
Код
 class cDoubleActiveObject
 {
 public:
   cDoubleActiveObject ();
   virtual ~cDoubleActiveObject () {}
   void Kill ();
   
 protected:
   virtual void FirstLoop   () = 0;  // первый тред, например ожидает событие от пайпа или от клиента
   virtual void SecondLoop  () = 0; //  второй тред, лопатит диск

   static DWORD WINAPI FirstThreadEntry (void *pArg);
   static DWORD WINAPI SecondThreadEntry (void *pArg);

   int             _isDying;
   Thread          _FirstThread;
   Thread          _SecondThread;
 };

 inline cDoubleActiveObject::cDoubleActiveObject ():_isDying (0),
#pragma warning(disable: 4355)
   _FirstThread (FirstThreadEntry, this),
   _SecondThread (SecondThreadEntry, this)
#pragma warning(default: 4355)
 {
 }
 
 inline void cDoubleActiveObject::Kill ()
 {
   _isDying++;
  _FirstThread.WaitForDeath ();
  _SecondThread.WaitForDeath ();
 }
 
 inline DWORD WINAPI cDoubleActiveObject::FirstThreadEntry (void* pArg)
 {
   cDoubleActiveObject *pActive = (cDoubleActiveObject *) pArg;
   pActive->FirstLoop ();
   return 0;
 }
 
 inline DWORD WINAPI cDoubleActiveObject::SecondThreadEntry (void* pArg)
 {
   cDoubleActiveObject * pActive = (cDoubleActiveObject *) pArg;
   pActive->SecondLoop ();
   return 0;
 }


типа, наглядный пример использования:
Код


HANDLE WaitClientEvent; // событие от клиента

class cServer : public cDoubleActiveObject
{
public:
   cServer(){}
  ~cServer(){ Kill();  // типа при удалении, коректно убираем за собой треды
  }
 void InitServer(){ _FirstThread.Resume(); _SecondThread.Resume(); }; // инициализация сервака, т.е. включение тредов

 void FirstLoop(); // тред ожидания события от клиента
 void SecondLoop(); // тред, который лопатит диск при простое сервака

protected:
private:
};

void cServer::FirstLoop()
{
 while (!_isDying)
 {
   WaitForSingleObject(WaitClientEvent,INFINITE); // ожидаем события от клиента
   {
     // получили событие от клиета и стопорим второй тред
     // потом, когда захотим, естественно включим трейд в работу обратно вызовом _SecondThread.Resume()
     _SecondThread.Suspend();
   }
 }
}

void cServer::SecondLoop()
{
 while (!_isDying)
 {
   // а тута лопатим диск, в общем что хотим то и делаем :)
 }
}

Вот, такой, простенький, пример мне залетел в голову.
Можно конечно и лучше придумать. А нужно ли мудрить? :)

Это сообщение отредактировал(а) bel_nikita - 4.11.2004, 00:50


--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
maxim1000
Дата 4.11.2004, 01:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



может, попробовать такое?
Код

...
while(true)
{
 DWORD bytes;
 PeekNamedPipe(pipe,0,0,0,&bytes,0);
 if(bytes==0)
 {
   //write something to some file
 }
 else
 {
   //work with client
 }
}
...

так даже Event не надо


--------------------
qqq
PM WWW   Вверх
NiJazz
Дата 4.11.2004, 08:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Jazz coder
****


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

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



maxim1000
На первый взгляд, вполне просто наглядно, но не хотелось бы иметь канал открытым, пока нет "событий" от клиента.
PM MAIL   Вверх
bel_nikita
Дата 4.11.2004, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

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



maxim1000
Цитата
может, попробовать такое?

Так, оно процессор загрузит на 100%. У меня при работе с COM портом, подобный пример грузит проц на 97%. Но как торлько перешел на тред с ожиданием события, точнее с автоматическим срабатывание, загрузка проца уменьшилась до 0% :)

NiJazz
Цитата
На первый взгляд, вполне просто наглядно, но не хотелось бы иметь канал открытым, пока нет "событий" от клиента.
ну если не хочется использовать два треда, тогда может вот такое подойдет:
Код

BOOL ClientExist = FALSE; // работаем ли с клиентом в данный момент. Где-нить глобально объявить для всей проги
....
while (true) // вечный двигатель
{
  DWORD Res = WaitForSingleObject(WaitClientEvent,100); // ожидаем событие от клиента и срабатываем каждые 100 мсек
  // проверяем пришло ли событие от клиента и работаем ли с клиентом в данный момент
  if ( Res == WAIT_OBJECT_0 || ClientExist == FALSE )
  {
    ClientExist = TRUE; // да, мы работает с клиентом
    // работаем с клиентом
   ...
    ClientExist = FALSE; // потом, когда отработали с клиентом, входим в состояние ожидания события и лопатим диск. Причем эту строчку можно сделать в другом куске кода
  }
  else
  {
    // лопатим диск, когда мы не работаем с клиентом
  }
}



--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
maxim1000
Дата 4.11.2004, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата
Так, оно процессор загрузит на 100%

оно грузит процессор настолько, насколько его грузят две альтернативные части программы
другое дело, что если притормозит одна из них, то притормозит и вторая - это минус...
Цитата
На первый взгляд, вполне просто наглядно, но не хотелось бы иметь канал открытым, пока нет "событий" от клиента.

а что здесь такого?
Добавлено @ 12:24
еще можно попробовать асинхронный режим функции ReadFile
Добавлено @ 12:25
(это, когда даешь команду "начать чтение", а потом тебе сообщают (возможно, с помощью Event), когда оно закончилось


--------------------
qqq
PM WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


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

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


 




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


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

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