IPB
ЛогинПароль:

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

 
 Ответить  Открыть новую тему 
> Синхронизация работы экземпляров приложения, VC++ 2008 EE
сообщение
Сообщение #1


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Требуется разработать приложение, которое, будучи запущенным несколько раз, выполняет отчёт до 5-ти, затем ждёт, пока другой экземпляр этого приложения сосчитает до 5-ти, после чего продолжает свой отчёт. Счёт выполняют все запущенные экземпляры приложения по очереди..

Воть..
начала с того, что запускаю эти самые экземпляры в отдельных потоках..трудность на этом этапе в том, что не пойму, что должно быть 3-им параметром в CreateThread..Объясните пожалуйста!


#define MAX_THREADS 3
//........
HANDLE hThreadArray[MAX_THREADS];
DWORD dwThreadIdArray[MAX_THREADS];

TCHAR szFileName[260];
OPENFILENAME ofn;
LPCWSTR lpFilter=TEXT("Executive\0*.EXE\0");
ZeroMemory(&ofn,sizeof(OPENFILENAME));
ofn.lStructSize=sizeof(OPENFILENAME) ;
ofn.hwndOwner=hWndMain;
ofn.hInstance=NULL;
ofn.lpstrFile = szFileName;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFileName);
ofn.lpstrFilter = lpFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn) && i<=3 )
{
i++;
hThreadArray[i] = CreateThread(
NULL,
0,
//???,
NULL,
0,
&dwThreadIdArray[i]);

}




Сообщение отредактировано: 18192123 -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






Цитата
не пойму, что должно быть 3-им параметром в CreateThread
Это должна быть точка входа (адрес) в функцию, выполняемую потоком. То есть, говоря просто, в твоем случае это и будет та функция, которая должна будет досчитать до 5-ти, потом подождать все остальные потоки, и опять посчитать до 5-ти, и т.д...

DWORD WINAPI thread_func(LPVOID lpParam)
{
// действия, выполняемые потоком
}

...
hThreadArray[i] = CreateThread(
NULL,
0,
thread_func, // передается вот так
NULL,
0,
&dwThreadIdArray[i]);
...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Теперь вопросы по сути задания...
В качестве метода синхронизации нужно использовать события (Event)...
Тогда в функцию, выполняемую потоком, я добавила OpenEvent (событие создаётся ранее) и перевод объекта-событие в занятое состояние...
Теперь, как я полагаю, должен осуществляться процесс счёта и ожидание, пока остальные экземпляры посчитают..И главный вопрос: что вообще нужно понимать под "посчитает до 5-ти"?...И как должна выглядеть организация процесса последовательного счёта каждым экземпляром??


DWORD WINAPI thread_func(LPVOID lpParam)
{
TCHAR szFileName[260];
OPENFILENAME ofn;
LPCWSTR lpFilter=TEXT("Executive\0*.EXE\0");
ZeroMemory(&ofn,sizeof(OPENFILENAME));
ofn.lStructSize=sizeof(OPENFILENAME) ;
ofn.hwndOwner=hWndMain;
ofn.hInstance=NULL;
ofn.lpstrFile = szFileName;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFileName);
ofn.lpstrFilter = lpFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (!GetOpenFileName(&ofn))
{
MessageBox(hWndMain,TEXT("Error by open file"),TEXT("Error"),MB_ICONERROR);
return 0;
}
SetEvent(OpenEvent(EVENT_MODIFY_STATE,
FALSE,
TEXT("MyEvent")));
//??Считаем...??
//освободить событие??


return 1;
}


void OnClickButThreads(HWND hwnd)
{
RECT Rect;
GetClientRect(hwnd,&Rect);

HANDLE hThreadArray[MAX_THREADS];
DWORD dwThreadIdArray[MAX_THREADS];

HANDLE hEvent=CreateEvent(NULL,
TRUE,
TRUE,
TEXT("MyEvent"));

if (i<=MAX_THREADS)
{
i++;
hThreadArray[i] = CreateThread(
NULL,
0,
thread_func,
NULL,
0,
&dwThreadIdArray[i]);

}
CloseHandle(hEvent);

}


 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Цитата
Теперь, как я полагаю, должен осуществляться процесс счёта и ожидание, пока остальные экземпляры посчитают
Правильно полагаешь.

Цитата
И главный вопрос: что вообще нужно понимать под "посчитает до 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.

Попробуй разобраться, что тут происходит, если не понятно - спрашивай.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Прежде всего такой вопрос: в приведённом выше коде потоки(!) разрабатываемого приложения выполняют счёт друг за другом...по заданию нужно, чтобы экземпляры(!!) приложения этим занимались..тогда вопрос: значит ли, что выполняющиеся последовательно потоки есть те самые экземпляры приложения? или мы в потоках должны позаботиться о запуске экземпляра приложения?

Теперь по коду..
Вот создали мы объект-событие, оно занято (FALSE),
теперь в цикле создаются потоки...
насколько я поняла, при создании 1-го же потока мы переходим в функцию thread_func.. (или нет? и сначала всё потоки создаются??)
RunMore истина, заходим в цикл -
событие у нас занято (изначально), тогда WaitForSingleObject должна "усыпить" наш 1-й поток...Тогда какой поток считать будет? 2-й? но разве он уже создан? Вот тут запуталась..Объясните пожалуйста..!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гость






Цитата
значит ли, что выполняющиеся последовательно потоки есть те самые экземпляры приложения? или мы в потоках должны позаботиться о запуске экземпляра приложения?
Стоп... Возникает 2 вопроса:

1) если у тебя работа с копиями приложения, зачем ты начала делать это с потоками?
2) при работе с потоками у тебя все понятно и прозрачно: есть основной поток приложения, который запускает несколько дочерних потоков, и только потом ставит Event, разрешающий потокам работать. Как по-твоему это должно происходить при запуске нескольких копий приложения? Ну, вот запустила ты приложение первый раз, и что? что должно произойти? Ждать, пока будет запущена еще одна копия? Или приложение само должно вызывать CreateProcess для создания самого себя себя?

Короче говоря: кто инициатор запуска нескольких копий приложения? Первая копия? Или пользователь?

Цитата
насколько я поняла, при создании 1-го же потока мы переходим в функцию thread_func..
Ну, и что? Переходим. Но пока не было SetEvent, каждый из созданных потоков будет ждать в WaitForSingleObject, пока событие не будет установлено. А установлено оно будет только после создания всех потоков.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(volvo @ 8.11.2008 22:30) *

Стоп... Возникает 2 вопроса:

1) если у тебя работа с копиями приложения, зачем ты начала делать это с потоками?

с потоками для того, что бы можно было для синхронизации работы использовать Event (последнее диктуется заданием)..
Цитата(volvo @ 8.11.2008 22:30) *

2) .....
Короче говоря: кто инициатор запуска нескольких копий приложения? Первая копия? Или пользователь?


в задании это не обговаривается..так что я думаю, разработчик приложения сам это решает с точки зрения выбора наиболее разумного способа (а что разумнее: первая копия запускает остальные копии приложения или пользователь, я не знаю..)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Гость






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

Цитата
а что разумнее: первая копия запускает остальные копии приложения или пользователь, я не знаю..
Я тем более не знаю. Решай. Я бы сделал запуск копий пользователем. Запущена одна копия - работает постоянно только она. Запустили вторую - работают первая и вторая поочередно, и т.д. Но вот тебе еще вопрос на засыпку: куда ты будешь выводить информацию о работе процесса? Каждый процесс - в свое окно? Тогда как следить за тем, что выполняются процессы именно в нужном порядке? Куда-нибудь в один из процессов? Тогда в какой именно?

Может, сделать первую копию с GUI, а все последующие уже без? То есть, окно будет только у первой копии, а все остальные будут работать с ним.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(volvo @ 8.11.2008 23:14) *

Решай. Я бы сделал запуск копий пользователем. Запущена одна копия - работает постоянно только она. Запустили вторую - работают первая и вторая поочередно, и т.д.
Может, сделать первую копию с GUI, а все последующие уже без? То есть, окно будет только у первой копии, а все остальные будут работать с ним.

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

Цитата(volvo @ 8.11.2008 23:14) *

Может, сделать первую копию с GUI, а все последующие уже без? То есть, окно будет только у первой копии, а все остальные будут работать с ним.

Ух ты..! Не знала, что так можно...Согласна, что это очень удобный способ отслеживать очередность действия копий..Только, как сделать - не представляю..
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Гость






Цитата
Только, как сделать - не представляю
Что мешает тебе сделать следующее: прежде всего проверять через OpenMutex наличие своего мьютекса? (как запрещается запуск второй копии приложения, знаешь? Тот же принцип, но тебе надо не запретить, а отследить) Если его нет - то это первая копия приложения, так? Вот только тогда и регистрировать класс окна, создавать окно, и создавать мьютекс, который при запуске следующей копии уже будет существовать. Если же мьютекс уже существовал, то это - не первая копия, и окно создавать уже не надо...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(volvo @ 9.11.2008 1:53) *

..как запрещается запуск второй копии приложения, знаешь? Тот же принцип, но тебе надо не запретить, а отследить..


Не знаю, как это делается...Объясните пожалуйста..!

 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Гость






В общем, задачка интересная, вот я набросал кое-что, тестировалось это в GCC, там все работает, лень запускать Студию smile.gif

Я не думаю, что будет очень много отличий... Возможно, что-то связанное с Юникодом опять всплывет, а так WinAPI он и в Африке WinAPI. Посмотри, как оно работает, я там прокомментировал кое-что, файл в кодировке UTF-8: Прикрепленный файл  main.cpp ( 6.35 килобайт ) Кол-во скачиваний: 419

 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(volvo @ 9.11.2008 17:14) *

В общем, задачка интересная, вот я набросал кое-что, тестировалось это в GCC, там все работает, лень запускать Студию smile.gif

Я не думаю, что будет очень много отличий... Возможно, что-то связанное с Юникодом опять всплывет, а так WinAPI он и в Африке WinAPI..

Спасибо большое!! Переделала под VS, всё работает как надо!
С отслеживанием запуска очередной копии разобралась,
но возник вопрос, связанный с установкой таймера для любой копии приложения - зачем это делается? чтобы ограничить повторение всей цепочки счёта по времени? или я не правильно поняла?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Гость






Цитата
возник вопрос, связанный с установкой таймера для любой копии приложения - зачем это делается? чтобы ограничить повторение всей цепочки счёта по времени? или я не правильно поняла?
Не очень люблю отвечать вопросом на вопрос, но здесь именно так и сделаю: а где еще можно организовать этот цикл "счета", чтобы программа работала, и при этом еще и другие приложения не лишались "права голоса"? Чтобы во время работы твоей программы происходила обработка всех событий, получаемых окном? Таймер - оптимальный выход. Когда приложение получает WM_TIMER, оно занимается ожиданием события и "счетом", в остальное время приложение обрабатывает любые другие сообщения.
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 23.10.2020 7:33
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name