Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.12.2012, 19:38   #1
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 671
По умолчанию Диалоговое окно::атомарное выполнение оконной процедуры

Здравствуйте. Хочу понять: почему оконная процедура диалогового окна не выполняется атомарно, даже при использовании критической секции?
Код:
#include <windows.h>
#include <tchar.h>

#define IDD_DIALOG1 100  

class Lock
{
	CRITICAL_SECTION access;

public:
	Lock()					{ InitializeCriticalSection(&this->access); }
	~Lock()					{ DeleteCriticalSection(&this->access); }
	void LockObject()		{ EnterCriticalSection(&this->access); }
	void UnlockObject()		{ LeaveCriticalSection(&this->access); }
}lock;


INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	lock.LockObject();			          // Занимаем критическую секцию.
	MessageBoxA(NULL, "", "", MB_OK);     // Получаем пачку сообщений, почему?
	lock.UnlockObject();			         // Освобождаем.

    return FALSE;
}

LPCTSTR DlgName = MAKEINTRESOURCE(IDD_DIALOG1);

int WINAPI _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR lpCmdLine,
                     int nCmdShow)
{
    DialogBoxParam(hInstance, DlgName, NULL, DialogProc, (LPARAM) NULL);
    return TRUE;
}

Последний раз редактировалось 220Volt; 14.12.2012 в 19:58.
220Volt вне форума Ответить с цитированием
Старый 14.12.2012, 20:27   #2
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 671
По умолчанию

Проверил - все действия совершаются от имени одного процесса:
Код:
INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	lock.LockObject();			    // Занимаем критическую секцию.
	char buf[50];
	itoa((int)GetCurrentProcessId(), buf, 10);
	MessageBoxA(NULL, buf, "", MB_OK);     // Получаем пачку сообщений, почему?
	lock.UnlockObject();			   // Освобождаем.

    return FALSE;
}

LPCTSTR DlgName = MAKEINTRESOURCE(IDD_DIALOG1);

int WINAPI _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR lpCmdLine,
                     int nCmdShow)
{
	char buf[50];
	itoa((int)GetCurrentProcessId(), buf, 10);
	MessageBoxA(NULL, buf, "Main process ID", MB_OK);

    DialogBoxParam(hInstance, DlgName, NULL, DialogProc, (LPARAM) NULL);
    return TRUE;
}
Чудеса какие-то …
220Volt вне форума Ответить с цитированием
Старый 14.12.2012, 21:08   #3
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 671
По умолчанию

С мьютексами такая же ерунда, ничего не пойму ...
Код:
#include <windows.h>
#include <tchar.h>

#define IDD_DIALOG1 100  
HANDLE mutex = CreateMutex(NULL, false, NULL);

INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if(WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0)   
		MessageBoxA(NULL, "Error", "", MB_OK);
	MessageBoxA(NULL, "", "", MB_OK);     // Получаем пачку сообщений, почему?
	ReleaseMutex(mutex);
    return FALSE;
}

LPCTSTR DlgName = MAKEINTRESOURCE(IDD_DIALOG1);

int WINAPI _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR lpCmdLine,
                     int nCmdShow)
{
	if( ! mutex )
	{
		MessageBoxA(NULL, "Error", "", MB_OK);
		return FALSE;
	}
    DialogBoxParam(hInstance, DlgName, NULL, DialogProc, (LPARAM) NULL);
    return TRUE;
}
220Volt вне форума Ответить с цитированием
Старый 14.12.2012, 21:49   #4
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Mutex и Critical Section реентрантны, а поскольку у вас все в одном потоке захват и того и другого срабатывает.

Зачем вам синхронизация там? Из другого потока диалоговую процедуру можно вызвать только вручную...

Вы явно путаетесь в терминологии.
waleri вне форума Ответить с цитированием
Старый 14.12.2012, 22:10   #5
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 671
По умолчанию

Вы, наверное, невнимательно посмотрели на код, получение нескольких MessageBox’эв, не дает мне никаких гарантий о порядке обработки сообщений. Я ведь не управляю циклом сообщений (для диалогового окна), я не знаю что там MS придумало. Может каждое сообщение обрабатывается в отдельном потоке.

Последний раз редактировалось 220Volt; 14.12.2012 в 22:24.
220Volt вне форума Ответить с цитированием
Старый 14.12.2012, 22:15   #6
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 671
По умолчанию

Другими словами - я не уверен, что не возникнет одновременной обработки нескольких сообщений одного и того же диалогового окна. Получение нескольких MessageBox'эв это подтверждает.
220Volt вне форума Ответить с цитированием
Старый 14.12.2012, 23:02   #7
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Цитата:
Сообщение от 220Volt Посмотреть сообщение
Может каждое сообщение обрабатывается в отдельном потоке.
Повторяю еще раз - вызвать диалговую процедуру из другого потока можно только "искуственным" путем, вручную. Если сообщения посылаются из другого потока оно посылаются синхронизировано.

Разберитесь с терминологией - что такое "атомарность", "многопоточность" и "реентрантность"
waleri вне форума Ответить с цитированием
Старый 15.12.2012, 06:45   #8
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 671
По умолчанию

Вам известно, что MessageBox() – создает модальное сообщение? А раз так, то поток, выполняющий оконную процедуру, не будет освобожден до тех пор, пока не будет закрыто этот MessageBox(). При наличии синхронизации, невозможно было бы получить несколько MessageBox() без закрытия предыдущего. Может мы друг друга не понимаем? Если Вам не сложно, скомпилируйте пример, думаю, все прояснится.
Насчет терминологии: атомарная операция – операция над данными, которую в каждый момент времени выполняет только один поток.
Поток – то чему выполняется процессорное время, часть процесса.
Реентрантность – исключение одновременного использование разделяемых данных.
220Volt вне форума Ответить с цитированием
Старый 15.12.2012, 06:48   #9
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 671
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Повторяю еще раз - вызвать диалговую процедуру из другого потока можно только "искуственным" путем, вручную...."многопоточность" и "реентрантность"
Вот здесь не понял. В этом одна из особенностей диалогового окна - я не вызываю оконную процедуру сам.
220Volt вне форума Ответить с цитированием
Старый 15.12.2012, 09:36   #10
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 671
По умолчанию

Провел небольшой эксперимент с целью посмотреть какие потоки выполняют оконную процедуру.
Код:
#include <windows.h>
#include <tchar.h>

#define IDD_DIALOG1 100  


class Lock
{
	CRITICAL_SECTION access;

public:
	Lock()					{ InitializeCriticalSection(&this->access); }
	~Lock()					{ DeleteCriticalSection(&this->access); }
	void LockObject()		{ EnterCriticalSection(&this->access); }
	void UnlockObject()		{ LeaveCriticalSection(&this->access); }
}lock;


INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	lock.LockObject();			    // Занимаем критическую секцию.
	char buf[50];
	itoa((int)GetCurrentThreadId(), buf, 10);
	MessageBoxA(NULL, buf, "", MB_OK);     // Получаем пачку сообщений, почему?
	lock.UnlockObject();			   // Освобождаем.

    return FALSE;
}

LPCTSTR DlgName = MAKEINTRESOURCE(IDD_DIALOG1);

int WINAPI _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR lpCmdLine,
                     int nCmdShow)
{
    DialogBoxParam(hInstance, DlgName, NULL, DialogProc, (LPARAM) NULL);
    return TRUE;
}
Результат: оконную процедуру выполняет один поток. Выходит, дело в странном поведении MessageBox'a. Спасибо за внимание.
220Volt вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Метода класса в качестве оконной процедуры формы GydruS Win Api 3 13.01.2012 12:11
Подмена оконной процедуры, Как правильно завершить? eduard93 Win Api 0 08.09.2011 16:45
Диалоговое окно Busine2009 Microsoft Office Word 0 01.08.2009 09:15
Диалоговое окно Михаил Юрьевич Общие вопросы Delphi 11 01.06.2009 20:31
Диалоговое окно Beggins Общие вопросы C/C++ 3 09.05.2008 05:03