1. Пользуйтесь тегами кода. - [code] ... [/code] 2. Точно указывайте язык, название и версию компилятора (интерпретатора). 3. Название темы должно быть информативным. В описании темы указываем язык!!!
Требуется разработать приложение, которое, будучи запущенным несколько раз, выполняет отчёт до 5-ти, затем ждёт, пока другой экземпляр этого приложения сосчитает до 5-ти, после чего продолжает свой отчёт. Счёт выполняют все запущенные экземпляры приложения по очереди..
Воть.. начала с того, что запускаю эти самые экземпляры в отдельных потоках..трудность на этом этапе в том, что не пойму, что должно быть 3-им параметром в CreateThread..Объясните пожалуйста!
не пойму, что должно быть 3-им параметром в CreateThread
Это должна быть точка входа (адрес) в функцию, выполняемую потоком. То есть, говоря просто, в твоем случае это и будет та функция, которая должна будет досчитать до 5-ти, потом подождать все остальные потоки, и опять посчитать до 5-ти, и т.д...
Теперь вопросы по сути задания... В качестве метода синхронизации нужно использовать события (Event)... Тогда в функцию, выполняемую потоком, я добавила OpenEvent (событие создаётся ранее) и перевод объекта-событие в занятое состояние... Теперь, как я полагаю, должен осуществляться процесс счёта и ожидание, пока остальные экземпляры посчитают..И главный вопрос: что вообще нужно понимать под "посчитает до 5-ти"?...И как должна выглядеть организация процесса последовательного счёта каждым экземпляром??
Теперь, как я полагаю, должен осуществляться процесс счёта и ожидание, пока остальные экземпляры посчитают
Правильно полагаешь.
Цитата
И главный вопрос: что вообще нужно понимать под "посчитает до 5-ти"?
Ну вот именно это и понимать: локальная переменная в функции потока меняет значение от 0 до 4 (или от 1 до 5). Чтобы было видно, что она-таки его меняет, можно, скажем, выводить текущее её (переменной) значение в какой-нибудь listbox. Чтобы заодно удостовериться, что потоки не "накладываются" один на другой, то есть, что не происходит так: переменная потока_1 становится = 1; переменная потока_1 становится = 2; переменная потока_2 становится = 1; переменная потока_1 становится = 3 ... По условию это недопустимо. Пока один поток работает - остальные спят...
Цитата
И как должна выглядеть организация процесса последовательного счёта каждым экземпляром??
Вот... А теперь - самое интересное. Я не знаю, что ты там делаешь в потоке (в смысле, в том коде, который привела), но вот такой код:
bool RunMore = true;
DWORD WINAPI thread_func(LPVOID lpParam) { int ID = *((int *)lpParam); // ID потока, чтобы было видно, какой из потоков пишет в hListBox
while(RunMore) { WaitForSingleObject(myEvent, INFINITE); char s[50] = {0}; for(int i = 0; i < 5; i++) { // считаем и показываем, что что-то происходит sprintf(s, "thread = %d; n = %d\0", ID, i); SendMessage(hListbox, LB_ADDSTRING, NULL, (LPARAM)s); } SetEvent(myEvent); }
return 0; }
... // Внимание: событие - с автосбросом, а не ручное, как было у тебя !!! myEvent = CreateEvent(NULL, FALSE, FALSE, NULL); int counter[THRD_COUNT] = {1, 2, 3}; // Это можно сделать и программно, я делал для простоты
for(int i = 0; i < THRD_COUNT; i++) { hThread[i] = CreateThread(NULL, 0, thread_func, (PVOID)&counter[i], 0, &dwThreadIdArray[i]); } SetEvent(myEvent); ...
заставляет последовательно выполняться все потоки до тех пор, пока по какой-то причине (скажем, нажатие кнопки, как сделал я) переменная RunMore не станет = false.
Попробуй разобраться, что тут происходит, если не понятно - спрашивай.
Прежде всего такой вопрос: в приведённом выше коде потоки(!) разрабатываемого приложения выполняют счёт друг за другом...по заданию нужно, чтобы экземпляры(!!) приложения этим занимались..тогда вопрос: значит ли, что выполняющиеся последовательно потоки есть те самые экземпляры приложения? или мы в потоках должны позаботиться о запуске экземпляра приложения?
Теперь по коду.. Вот создали мы объект-событие, оно занято (FALSE), теперь в цикле создаются потоки... насколько я поняла, при создании 1-го же потока мы переходим в функцию thread_func.. (или нет? и сначала всё потоки создаются??) RunMore истина, заходим в цикл - событие у нас занято (изначально), тогда WaitForSingleObject должна "усыпить" наш 1-й поток...Тогда какой поток считать будет? 2-й? но разве он уже создан? Вот тут запуталась..Объясните пожалуйста..!
значит ли, что выполняющиеся последовательно потоки есть те самые экземпляры приложения? или мы в потоках должны позаботиться о запуске экземпляра приложения?
Стоп... Возникает 2 вопроса:
1) если у тебя работа с копиями приложения, зачем ты начала делать это с потоками? 2) при работе с потоками у тебя все понятно и прозрачно: есть основной поток приложения, который запускает несколько дочерних потоков, и только потом ставит Event, разрешающий потокам работать. Как по-твоему это должно происходить при запуске нескольких копий приложения? Ну, вот запустила ты приложение первый раз, и что? что должно произойти? Ждать, пока будет запущена еще одна копия? Или приложение само должно вызывать CreateProcess для создания самого себя себя?
Короче говоря: кто инициатор запуска нескольких копий приложения? Первая копия? Или пользователь?
Цитата
насколько я поняла, при создании 1-го же потока мы переходим в функцию thread_func..
Ну, и что? Переходим. Но пока не было SetEvent, каждый из созданных потоков будет ждать в WaitForSingleObject, пока событие не будет установлено. А установлено оно будет только после создания всех потоков.
1) если у тебя работа с копиями приложения, зачем ты начала делать это с потоками?
с потоками для того, что бы можно было для синхронизации работы использовать Event (последнее диктуется заданием)..
Цитата(volvo @ 8.11.2008 22:30)
2) ..... Короче говоря: кто инициатор запуска нескольких копий приложения? Первая копия? Или пользователь?
в задании это не обговаривается..так что я думаю, разработчик приложения сам это решает с точки зрения выбора наиболее разумного способа (а что разумнее: первая копия запускает остальные копии приложения или пользователь, я не знаю..)
с потоками для того, что бы можно было для синхронизации работы использовать Event
Event тоже можно использовать для межпроцессного взаимодействия, только надо делать это аккуратно...
Цитата
а что разумнее: первая копия запускает остальные копии приложения или пользователь, я не знаю..
Я тем более не знаю. Решай. Я бы сделал запуск копий пользователем. Запущена одна копия - работает постоянно только она. Запустили вторую - работают первая и вторая поочередно, и т.д. Но вот тебе еще вопрос на засыпку: куда ты будешь выводить информацию о работе процесса? Каждый процесс - в свое окно? Тогда как следить за тем, что выполняются процессы именно в нужном порядке? Куда-нибудь в один из процессов? Тогда в какой именно?
Может, сделать первую копию с GUI, а все последующие уже без? То есть, окно будет только у первой копии, а все остальные будут работать с ним.
Решай. Я бы сделал запуск копий пользователем. Запущена одна копия - работает постоянно только она. Запустили вторую - работают первая и вторая поочередно, и т.д. Может, сделать первую копию с GUI, а все последующие уже без? То есть, окно будет только у первой копии, а все остальные будут работать с ним.
Да, я согласна с тем, что запуск копий будет производиться пользователем
Цитата(volvo @ 8.11.2008 23:14)
Может, сделать первую копию с GUI, а все последующие уже без? То есть, окно будет только у первой копии, а все остальные будут работать с ним.
Ух ты..! Не знала, что так можно...Согласна, что это очень удобный способ отслеживать очередность действия копий..Только, как сделать - не представляю..
Что мешает тебе сделать следующее: прежде всего проверять через OpenMutex наличие своего мьютекса? (как запрещается запуск второй копии приложения, знаешь? Тот же принцип, но тебе надо не запретить, а отследить) Если его нет - то это первая копия приложения, так? Вот только тогда и регистрировать класс окна, создавать окно, и создавать мьютекс, который при запуске следующей копии уже будет существовать. Если же мьютекс уже существовал, то это - не первая копия, и окно создавать уже не надо...
В общем, задачка интересная, вот я набросал кое-что, тестировалось это в GCC, там все работает, лень запускать Студию
Я не думаю, что будет очень много отличий... Возможно, что-то связанное с Юникодом опять всплывет, а так WinAPI он и в Африке WinAPI. Посмотри, как оно работает, я там прокомментировал кое-что, файл в кодировке UTF-8: main.cpp ( 6.35 килобайт )
Кол-во скачиваний: 541
В общем, задачка интересная, вот я набросал кое-что, тестировалось это в GCC, там все работает, лень запускать Студию
Я не думаю, что будет очень много отличий... Возможно, что-то связанное с Юникодом опять всплывет, а так WinAPI он и в Африке WinAPI..
Спасибо большое!! Переделала под VS, всё работает как надо! С отслеживанием запуска очередной копии разобралась, но возник вопрос, связанный с установкой таймера для любой копии приложения - зачем это делается? чтобы ограничить повторение всей цепочки счёта по времени? или я не правильно поняла?
возник вопрос, связанный с установкой таймера для любой копии приложения - зачем это делается? чтобы ограничить повторение всей цепочки счёта по времени? или я не правильно поняла?
Не очень люблю отвечать вопросом на вопрос, но здесь именно так и сделаю: а где еще можно организовать этот цикл "счета", чтобы программа работала, и при этом еще и другие приложения не лишались "права голоса"? Чтобы во время работы твоей программы происходила обработка всех событий, получаемых окном? Таймер - оптимальный выход. Когда приложение получает WM_TIMER, оно занимается ожиданием события и "счетом", в остальное время приложение обрабатывает любые другие сообщения.