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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Открываю файл -> операционка виснет 
V
    Опции темы
neosapient
  Дата 19.12.2006, 00:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Здравствуйте.

Возникла проблема на ровном месте, немогу понять откуда лезет.
Задача. 
Открыть файл, считать оттуда данные определенной структуры, закрыть файл.

Решешал задачку так:
Создал диалог.
В момент прихода сообщения WM_INITDIALOG создается дополнительный поток AnalysFile(...).
В этой функции открываю файл test.txt на чтение побайтно. Создаю заполняемую структуру и указатель на нее. Далее пока файл не кончиться, заполняю побайтно через указатель все поля структуры. По окончании файла, закрываю соединение. Дополнительный поток закрываеться.

Код

#include <windows.h>
#include <stdio.h>
#include "resource.h"

LRESULT CALLBACK DialogProc (HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam);
DWORD WINAPI AnalysFile(LPVOID);

typedef struct DATA{
    char first;
    short second;
    int third;
};

WINAPI WinMain // точка входа в Windows программу
(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 LPSTR lpCmdLine, int nCmdShow)
{
    DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG),0,(DLGPROC)DialogProc);
    return 0;
}

LRESULT CALLBACK DialogProc (HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)
{
    static HANDLE hThread;
    switch(msg)
    {
    case WM_INITDIALOG :  
        hThread = CreateThread(NULL, 0, AnalysFile, (LPVOID)hDlg, 0, 0);
        break;
    case WM_COMMAND:  
        switch (LOWORD(wParam))
        {
        case IDCANCEL:
            TerminateThread(hThread,0);
            CloseHandle( hThread );
            EndDialog(hDlg, LOWORD(wParam));
            return TRUE;
        case IDOK:
            break;         
        }
    break;         
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        break;
    }
return 0;
}

DWORD WINAPI AnalysFile(LPVOID hDlg)
{
DATA Data;
char *pData;
pData = (char*) (&Data);
FILE* file;
if((file = fopen("test.txt","r"))==NULL){
    MessageBox((HWND)hDlg,"Не могу открыть файл","error",MB_OK);
    return 0;
}
int i;
do{
    for(i=0;i<sizeof(DATA);i++)
        *(pData+i)=getc(file);
}while(!feof(file));
fclose(file);
return 0;
}

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

Подскажите, ЧТО не так делаю.

Доп. вопрос: когда происходит считывание байтов из файла и их побайтная запись в структуру, то создается такое впечатление, что char у меня в два байта?! В том смысле, что при i равном 1 из файла считывается значение b однако оно пишется в сокрытую область стуктуры. Может происходит какое то выравнивание длинны структуры до значения кратного 4 байтам?

Это сообщение отредактировал(а) neosapient - 19.12.2006, 00:35

Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  getdataTest.rar 3,41 Kb
PM MAIL   Вверх
dumb
Дата 19.12.2006, 02:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

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



Цитата(neosapient @  19.12.2006,  00:10 Найти цитируемый пост)
Может происходит какое то выравнивание длинны структуры до значения кратного 4 байтам?

почти угадал. только выравнивается не размер структуры, а сами поля. значение границ задается опциями, по умолчанию - компилер сам "придумывает" как выравнивать(например в твоем случае он выровнял первое поле до двух байт, чтоб вкупе со вторым они заняли 4 байта).
когда гоняешь структуры "наружу"(файл,сокет,итд), надо ставить для них выравнивание в 1.
Код

#pragma pack(push, 1)
typedef struct DATA{
    char first;
    short second;
    int third;
};
#pragma pack(pop)

PM MAIL   Вверх
Earnest
Дата 19.12.2006, 08:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Нехорошо прерывать поток через TerminateThread. Это для аварийного прерывания, когда поток не отвечает. При этом не освобождаются ресурсы и не происходят другие правильные вещи. Для такой маленькой программы как твоя, это, возможно и ерунда, но для реальных проектов - отнюдь нет.
Поток должен завершаться сам. Для того чтобы завершить его извне, нужно создать, например, событие (event). Управляющий поток сигнализирует событие, а рабочий поток должен в своем цикле отслеживать, не активно ли событие, и завершаться, если это так.
Кроме того, поток вполне может завершить до того, как ты нажмешь Cancel. И это тоже нужно проверять.


--------------------
...
PM   Вверх
neosapient
Дата 19.12.2006, 09:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



За "выравние полей" спасибо, не знал.

А по поводу основного вопроса:
Если я создаю доп поток не на сообщение WM_INITDIALOG, а на WM_COMMAND -> IDOK, то ничего не виснет. Щелкаю на кнопочку ОК и доп поток запускается.
Но мне хочется создавать доп поток на сообщение WM_INITDIALOG
PM MAIL   Вверх
Aleksandor
Дата 19.12.2006, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Практик
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 22.11.2005
Где: россия, зеленогра д

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



Кажись читал у Рихтера что нельзя пользовать CreateThread если используются функции run-time. Чтение из файла тоже как-то странно оформлено, имхо.


--------------------
Call out Gouranga be happy!!!
Gouranga Gouranga Gouranga ....
That which brings the highest happiness!!
PM MAIL   Вверх
neosapient
Дата 23.12.2006, 21:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Aleksandor, извени, а что относиться к run-time функциям? и на что их заменить?..

Цитата

Чтение из файла тоже как-то странно оформлено?

Ну, функции взяты из stdio.h
PM MAIL   Вверх
Aleksandor
Дата 23.12.2006, 22:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Практик
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 22.11.2005
Где: россия, зеленогра д

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



Щас посмотрел, у диалоговой процедуры нет родительского окна. Процедура диалоговая и WinMain как-бы в одном стакане. Мне кажется это не есть хорошо. 

Run-time функции это те самые fopen, getc, time, strchr и т.д. Вместо CreateThread лучше заюзать _beginthreadex Почему-ищи в MSDN по слову _beginthreadex

Насчет странного это чтение из файла побайтово-это слишком неэффективно. Кстати, в файле может и не быть feof. Тогда чтение зависнет навеки веков  smile 
Лучше читать сразу весь файл или какую-то его часть в буфер, а потом анализировать. Или сделать file mapping - тогда и буфер не нужен.




--------------------
Call out Gouranga be happy!!!
Gouranga Gouranga Gouranga ....
That which brings the highest happiness!!
PM MAIL   Вверх
neosapient
Дата 24.12.2006, 22:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Щас посмотрел, у диалоговой процедуры нет родительского окна. Процедура диалоговая и WinMain как-бы в одном стакане. Мне кажется это не есть хорошо. 

Ну попытался разделить... Создаю окно, делаю дочерний диалог, делаю поток. Все работает.
Второй эксперимент - Создаю окно, делаю дочерний диалог и показываю, делаю поток. Все виснет. (этот пример в приложении)

Подозрение на прорисовку окна. Как исправлять?

Цитата

Кстати, в файле может и не быть feof. 

Угу, так и есть, поставил временную заглушку.

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  getdataTestExample.rar 38,57 Kb
PM MAIL   Вверх
Aleksandor
Дата 25.12.2006, 00:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Практик
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 22.11.2005
Где: россия, зеленогра д

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



Вот, у меня вроде пашет...  smile 

Это сообщение отредактировал(а) Aleksandor - 25.12.2006, 06:38

Присоединённый файл ( Кол-во скачиваний: 5 )
Присоединённый файл  000my.rar 5,00 Kb


--------------------
Call out Gouranga be happy!!!
Gouranga Gouranga Gouranga ....
That which brings the highest happiness!!
PM MAIL   Вверх
oper54
Дата 25.12.2006, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата

#pragma pack(push, 1)
typedef struct DATA{
    char first;
    short second;
    int third;
};
#pragma pack(pop)

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

ИМХО по меньше пользоватся надо дерективами компилера, ибо не у всех 
компилеров они такие есть =)
PM MAIL   Вверх
neosapient
Дата 25.12.2006, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Вот, у меня вроде пашет... 

Aleksandor, а ты поставь брякпоинт на начало функции AnalysFile и будет тебе "шастъе"  smile 
В общем пока не пашет...


oper54, данные структурированы и я честно говоря не предсталяю как тут применить GlobalAlloc, вместо выравнивания полей. Поясни примером, что имелось в виду...
PM MAIL   Вверх
Aleksandor
Дата 25.12.2006, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Практик
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 22.11.2005
Где: россия, зеленогра д

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



Я конешно сильно извиняюсь... Но... зачем ставить breakpoint на начале AnalyseFile  smile 


--------------------
Call out Gouranga be happy!!!
Gouranga Gouranga Gouranga ....
That which brings the highest happiness!!
PM MAIL   Вверх
neosapient
Дата 25.12.2006, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

зачем ставить breakpoint на начале AnalyseFile  

Чтоб, проверить правильность работы...

И вообще надо чтоб в любой части программы можно было ставить breakpoint, чтоб контролировать правильность работы.
А то как разобраться с кодом черного ящика...
PM MAIL   Вверх
Aleksandor
Дата 25.12.2006, 22:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Практик
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 22.11.2005
Где: россия, зеленогра д

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



Не обязательно  smile  Тут можно скорее запутаться. Гораздо проще и эффективнее поставить например Beep(5000, 200); в нужной точке чтобы проконтролировать прохождение кода. К тому же результат работы виден сразу  smile 


--------------------
Call out Gouranga be happy!!!
Gouranga Gouranga Gouranga ....
That which brings the highest happiness!!
PM MAIL   Вверх
neosapient
Дата 25.12.2006, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Гораздо проще и эффективнее поставить например Beep(5000, 200); в нужной точке чтобы проконтролировать прохождение кода

А как контролировать поля структур далее???  smile 

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.0576 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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