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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Задержка выполнения функции, Возможно ли? 
:(
    Опции темы
ApolloKiD
Дата 14.3.2013, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Доброго времени суток.

После долгого поиска в интернете, пришёл сюда за помощью.

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

Пример:
Код

BOOL Proc1()
{
    // ---- Здесь нужно остановить время до проверки
    if(DataReceived == 1)
        return TRUE;

    return FALSE;
}

void Proc2()
{
    // ---- А это функция принятия данных, где после установки DataReceived = 1; надо разморозить время в Proc1() чтобы она продолжила работу.
}


Пробовал с критическими секциями, но что-то не получается.

Буду благодарен любым советам.

Заранее спасибо.
PM MAIL   Вверх
xvr
Дата 14.3.2013, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(ApolloKiD @  14.3.2013,  12:37 Найти цитируемый пост)
Дело в том что, есть функция, в которой нужно остановить время, по началу пробовал циклом, но цикл останавливает время во всём процессе, тем самым другие функции не могут выполнить свою работу, пока цикл не закончится.

Разумеется. И любые другие способы так же заморозят все, пока не кончится функция.

Вам нужен параллельно выполняющийся поток - его можно приостановить, при этом функции в другом потоке будут выполняться.

См. CreateThread (а лучше _beginthread), CreateEvent и WaitForSingleObject


Это сообщение отредактировал(а) xvr - 14.3.2013, 13:37
PM MAIL   Вверх
ApolloKiD
Дата 14.3.2013, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Благодарю за ответ.

А есть способ без потоков?

Например как с критическими секциями: 
Код

void Proc0()
{
    EnterCriticalSection(&m_CR); // ---- Первый вход в секцию
    // ---- 
    if(Proc1())
    {
        LeaveCriticalSection(&m_CR);  // ----  Второй выход из секции
    }
}
BOOL Proc1()
{
    EnterCriticalSection(&m_CR); // ---- Второй вход
    // ---- Сюда мы не попадем пока Proc2() не выйдет из секции.
    if(DataReceived == 1)
    {    
        return TRUE;
    }
    return FALSE;
}
void Proc2()
{
    // ---- А это функция принятия данных, где после установки DataReceived = 1; надо разморозить время в Proc1() чтобы она продолжила работу.
    LeaveCriticalSection(&m_CR); // ----  Первый выход из секции
}


Но к сожалению, этот способ не работает, критическую секцию он обходит всё равно и идет дальше, не смотря на то, что он должен остановится.

Или я не так понял работу критических секций.

Это сообщение отредактировал(а) ApolloKiD - 14.3.2013, 14:03
PM MAIL   Вверх
feodorv
Дата 14.3.2013, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

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



Цитата(ApolloKiD @  14.3.2013,  15:02 Найти цитируемый пост)
А есть способ без потоков?

Цитата(ApolloKiD @  14.3.2013,  15:02 Найти цитируемый пост)
этот способ не работает

А зачем критические секции без потоков?

Не ясна структура Вашей программы. Она однопоточная, и если вы приостановите выполнение этого потока в какой-то функции, то, естественно, приостановится весь поток.
Но Вам этого не надо, а надо что-то другое. Что делают другие функции в те моменты, когда Вам хочется приостановить время? Как вообще вызывается proc2, которая должна "пробуждать" приостановленную Proc0?

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


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
ApolloKiD
Дата 14.3.2013, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Proc2() вызывается при принятии данных.

Вот как всё выглядит на самом деле:
Код

void Proc0()
{
    // ---- Здесь отправляются данные для обработки

    /* Здесь надо заморозить функцию сразу после отправки данных, для ожидания ответа. */
    if(Proc1())
    {
        // ... тут действие
    }
}
BOOL Proc1()
{
    // ---- Сюда мы не попадем пока Proc2() не приймет данные.
    if(Proc2() == 1) // Дело в том что данные могут не прийти сразу, а с какой-то паузой, и возвращаемое значение будет не той что надо. 
    {    
        return TRUE;
    }
    return FALSE;
}
int Proc2() //Функция вызывается когда данные приходят
{
    // ---- Данные пришли, теперь можно разморозить функцию Proc0().
    return DataReceived;
}


Это сообщение отредактировал(а) ApolloKiD - 14.3.2013, 15:36
PM MAIL   Вверх
baldina
Дата 14.3.2013, 16:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

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



ApolloKiD, раз это асинхронный ввод/вывод, одной функцией не выйдет.
при асинхронной обработке одна чать программы посылает запрос и устанавливает обработчик (функцию), срабатывающую на прием данных.
придется разбить код Proc0 на две части: отправка данных и получение данных. 
как именно это делать зависит от того, чем (какой библиотекой/функциями) вы пользуетесь для отправки/получения

Добавлено через 2 минуты и 45 секунд
если не вдаваться в подробности, ваш код должен быть переписан примерно так:
Код

void Proc0()
{
    // ---- Здесь отправляются данные для обработки
}
/*
BOOL Proc1()
{
    // ---- Сюда мы не попадем пока Proc2() не приймет данные.
    if(Proc2() == 1) // Дело в том что данные могут не прийти сразу, а с какой-то паузой, и возвращаемое значение будет не той что надо. 
    {    
        return TRUE;
    }
    return FALSE;
}
*/
void Proc2() //Функция вызывается когда данные приходят
{
    // ---- Данные пришли, теперь можно разморозить функцию Proc0().
    {
        // ... тут действие
    }
}


PM MAIL   Вверх
volatile
Дата 14.3.2013, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

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



ApolloKiD, я так понял у вас приложение однопоточное.
Не ясно только куда/от куда вы посылаете/прнимаете данные.
Другому приложению, чтоли? (походу, если по сети, то тоже значит что другому приложению)

Если все происходит внутри одного приложения, и оно однопоточно, то вообще ничего не надо.
Нужно просто правильно организовать последовательность вызовов.

PM MAIL   Вверх
k0rvin
Дата 14.3.2013, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 442
Регистрация: 24.1.2010

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



Ниче не понял. Наверное так, например:
Код

void Proc0()
{
    SendData(data);
    int response = RecieveResponse();
    Proc1();
    if (response == 1)
    {
        // ... тут действие
    }
}

void Proc1()
{
    // ---- Сюда мы не попадем пока Proc2() не приймет данные.
}


Это сообщение отредактировал(а) k0rvin - 14.3.2013, 19:05


--------------------
“Object-oriented design is the roman numerals of computing.” — Rob Pike
All software sucks
PM MAIL   Вверх
ApolloKiD
Дата 14.3.2013, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



baldina, WinSock.
volatile, Да, вы правильно поняли, другому приложению.
k0rvin, Так не пробовал, потому что данные сначала попадают на протокол и там идет функция принятия данных.

Пример:

Код

void Protocol(BYTE HeadCode, unsigned char * aRecv, int aLen)
{
    switch (HeadCode)
    {
    case 0x00:
        {
            // ---- Здесь Proc2() принимает данные
        }
        break;
    }
}

PM MAIL   Вверх
volatile
Дата 14.3.2013, 23:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

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



ApolloKiD, не вникая глубого, скажу имхо, 
Проще всего вам в данном случае сделать второй поток, и всю функцию ожидания ответа запустить в нем.

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





PM MAIL   Вверх
baldina
Дата 15.3.2013, 17:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

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



ApolloKiD, 

установление соединения со стороны сервера выглядит так:
1. подготовка соединения, начало прослушивания
create socket(protocol) -> bind (port) -> listen()
2. установка соединения (инициированного клиентом)
accept()
в этот момент сервер начинает обслуживает данное соединение. что бы дать ему возможность отвечать и на другие запросы, нужно либо мультиплексировать обслуживание (асинхронный ввод/вывод), либо (проще, но накладнее) создать отдельный поток для данного соединения.
3. send()/recive() для данного соединения

со стороны клиента чуть иначе, но похоже
1. подготовка соединения
create socket(protocol)
2. установка (инициация) соединения
сonnect()
в этот момент клиент готов читать и писать. если параллельно с обменом данными нужно делать другую работу (например, данные приходят время от времени, и нужно их отображать по мере поступления, "в фоне"), recive() нужно делать либо в отдельном потоке, либо асинхронно.
3. send()/recive() для данного соединения

для асинхронного обмена можно использовать 
1. pool() или select(), которые могут проверить состояние сокета(ов) без блокировки (через таймаут)
2. неблокирующий режим. для перевода в этот режим используется ioctlsocket(). теперь recv() будет не блокировать поток, а возвращать управление сразу (с ошибкой, если данные еще не пришли)
3. WSAAsyncSelect - вариант неблокирующего select() для оконных приложений, факт готовности приема/отправки данных передается через очередь сообщений windows
PM MAIL   Вверх
feodorv
Дата 15.3.2013, 21:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

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



Цитата(baldina @  15.3.2013,  18:19 Найти цитируемый пост)
WSAAsyncSelect - вариант неблокирующего select() для оконных приложений

Или WSAEventSelect/WSAWaitForMultipleEvents для не оконных)))


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
baldina
Дата 15.3.2013, 22:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

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



виноват. WSAAsyncSelect
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "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.0690 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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