Книги
чёрным по белому
Главное меню
Главная О нас Добавить материал Поиск по сайту Карта книг Карта сайта
Книги
Археология Архитектура Бизнес Биология Ветеринария Военная промышленность География Геология Гороскоп Дизайн Журналы Инженерия Информационные ресурсы Искусство История Компьютерная литература Криптология Кулинария Культура Лингвистика Математика Медицина Менеджмент Металлургия Минералогия Музыка Научная литература Нумизматика Образование Охота Педагогика Политика Промышленные производства Психология Путеводители Религия Рыбалка Садоводство Саморазвитие Семиотика Социология Спорт Столярное дело Строительство Техника Туризм Фантастика Физика Футурология Химия Художественная литература Экология Экономика Электроника Энергетика Этика Юриспруденция
Новые книги
Цуканов Б.И. "Время в психике человека" (Медицина)

Суворов С. "Танк Т-64. Первенец танков 2-го поколения " (Военная промышленность)

Нестеров В.А. "Основы проэктирования ракет класса воздух- воздух и авиационных катапульных установок для них" (Военная промышленность)

Фогль Б. "101 вопрос, который задала бы ваша кошка своему ветеринару если бы умела говорить" (Ветеринария)

Яблоков Н.П. "Криминалистика" (Юриспруденция)
Реклама

C++. Энциклопедия пользователя - Либерти Дж.

Либерти Дж. C++. Энциклопедия пользователя — Москва, 2001. — 581 c.
Скачать (прямая ссылка): enciklopediyapolzovatelya2001.djvu
Предыдущая << 1 .. 58 59 60 61 62 63 < 64 > 65 66 67 68 69 70 .. 280 >> Следующая

134
Вопросы реализации
Часть II
DDX_Radio(pDX, IDC_RADIO_NONE, m_RadioButtonValue);
Пока выполняется мастер, автор также отобразил каждую кнопку на метод, так чтобы, когда пользователь выберет один из переключателей, вызвался бы связанный метод:
ON_BN_CLICKED(IDC_RADIO_NONE, OnRadioNone)
ONZBNICLICKED<IDC~RADIO_MUTEX, OnRadioMutex)
°N_BN~CLICKED(IDC~RADIO_CRITICAL_SECTION, OnRadioCriticalSection)
Например, когда пользователь щелкает на кнопке Mutex (IDC_RADIO_MUTEX), вызывается метод OnRadioMutex(), как показано ниже:
void CThreadsUnleashedDlg::OnRadioMutex()
{
UpdateData () ;
CStatic * pStatic = ( (CStatic *) (GetDlgItem(IDC_STATIC_STATUS))); pStatic->SetWindowText("Using Mutex");
}
Первое, что делает данный метод, — обновляет связанную переменную (m_RadioButtonNone) и печатает сообщение состояния на строке состояния.
Вернемся к ThreadFunction(). После того как мы определили, что не выдерживается пауза, переключаемся на значение m_RadioButtonNone, которое, как вы теперь знаете, соответствует переключателю, выбранному пользователем. Для проверки оператора switch используем перечисляемую константу:
enum synch { aNONE, aCRITICAL_SECTION, sMUTEX, aEVENT} ;
Это позволяет легче расшифровать назначение программного кода. Если значение sNone (нуль), то это означает, что выбрана первая кнопка None, печатается значение m_Value и увеличивается. Если выбрана кнопка Critical Section либо Mutex, то автор ограничивает вызов функции приращения кодом для управления синхронизирующим устройством.
В случае, когда выбран переключатель Critical Section, автор блокирует переменную m_CS критического раздела диалогового окна, обновляет значение и затем разблокирует его:
case sCRITICAL_SECTION: // критический раздел
pThis->m_CS.Lock(); // ожидание невозможно
s.Format("Current value: %d",pThis->m_Value);
Sleep (rand() % 1000); pThis->m_Value++; pThis->m_CS.Unlock(); break;
В случае, когда выбран переключатель Mutex, имеется возможность большего контроля. Автор создает объект CSingleLock, передавая адрес мютекса, а затем требует замок, указывая время тайм-аута. Если мютекс блокирован в пределах отведенного времени, то автор двигается вперед, печатает и обновляет значение. Если мютекс недоступен в пределах отведенного времени, то работа прекращается и отображается предупреждающее сообщение. Это предотвращает поток от "зависания", когда ожидается мютекс, который никогда не освободится.
Если пользователь щелкает на кнопке Start Thread 3, инициализируется несколько иная последовательность событий:
void CThreadsUnleashedDlg::OnButtonStartT3()
{
CButton * pB = (CButton *) GetDlgltem (IDC_BUTTON_START_T3) ; pB->EnableWindow (false) ; if ( ! m_MTC )
{
m_MTC = new CMyThreadClass(this);
BOOL bRc = m MTC->CreateThread() ;
if ( ! bRc )~
{
CString msg("Unable to start thread!\n");
AfxMessageBox(msg);
// JLTODO: послать завершающее сообщение
)
m_MTC->PostThreadMessage( WM_START_WORK, 0, 0 );
Использование каркасов приложений 1 11С
Глава 5 ¦ Ijj
CountThreads () ;
}
}
И вновь мы обесцвечиваем кнопку, но на этот раз проверяем, имеет ли значение NULL переменная-член, которая указывает на порожденный от CWinThread объект. Предполагая, что да, мы готовы создать новый экземпляр класса потока.
Обычно действительно проверяется, имеет ли указатель значение NULL, однако в данном программном коде мы знаем, что это не так, и потому оператор if можно переписать, используя ASSERT.
ASSERT ( ! m_MTC ) ;
Поскольку мы обесцветили кнопку, данный поток существовать уже не может. Автор предоставил этот путь, чтобы вы могли воспользоваться им в будущем, когда будете создавать или разрушать потоки для объектов.
Цель заключается в реализации объекта типа CMyThreadClass. Данный класс порожден от CWinThread и, таким образом, способен управлять потоком Windows:
class CMyThreadClass : public CWinThread
Создание потока представляет собой двухэтапный процесс. На первом этапе реализуется объект потока: m_MTC = new CMyThreadClass(this);
На втором этапе создается сам поток:
BOOL bRc = m_MTC->CreateThread();
Обратите внимание на разницу. Когда мы создаем экземпляр, используя оператор new, то создаем объект, но не создаем поток Windows. Поток создается путем обращения к CreateThread(). Мы говорим об объекте и о потоке так, будто это одно и то же, но это разные вещи.
После того как поток запущен, мы хотим, чтобы он начал работать, но не хотим вызывать его метод StartWork() прямо. Если так сделать, то поток зависнет вплоть до возврата методом управления (что никогда не произойдет). Вместо этого мы хотим асинхронно послать сообщение данному потоку и указать ему начать работу. Такое указание посылается методом PostThreadMessage(), который возвращается немедленно:
m_MTC->PostThreadMessage( WM_START_WORK, 0, 0 );
Этот оператор посылает потоку определенное пользователем сообщение со значением WM_START_WORK. Данное значение также определяется в файле constants.h, как показано ниже:
const int WM_START_WORK = WM_USER + 1;
Когда поток обнаруживает это сообщение, то отображает его на метод-член класса диспетчерской картой:
Предыдущая << 1 .. 58 59 60 61 62 63 < 64 > 65 66 67 68 69 70 .. 280 >> Следующая