Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Каким способом быстрее обработать файл? Использовать потоки, DLL или конс. приложен

490
11 февраля 2008 года
frid-karatel
357 / / 15.09.2007
Приветствую!

Имеется приложение, которое выполняет много функций во время работы с файлами. Файлы где-то 20-25 Мб. Требуется искать в них информацию и перекодировать ее из wchar в обычный char.

Дело в том, что вычисление таких операций тратит много времени. Интересует такой вопрос - может быть стоит как-то вынести такие функции за пределы программы, например, в потоки или написать маленькие консольные подпрограммы, которые будут выполнятся через командную строку и передавать данные основной программе?
11
12 февраля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: frid-karatel
Приветствую!

Имеется приложение, которое выполняет много функций во время работы с файлами. Файлы где-то 20-25 Мб. Требуется искать в них информацию и перекодировать ее из wchar в обычный char.

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



примерно такую задачу решил следующим образом:
есть список файлов, делаю

Код:
в *.hpp:
deque <HANDLE> dqThread;

в *.cpp:
цикл
dqThread.push_back(CreateThread( NULL , 0 , CheckFile, (LPVOID)FileName, 0 , NULL ));
цикл

сам процесс:
DWORD WINAPI CheckFile (LPVOID FileName)
{
  // обработка файла
}

на форме кнопка "Отмена" в обработчике которой цикл по всем процессам и их завершение

ЗЫ: быстрее вряд ли будет, но с основной программой можно будет работать, пока файлы обрабатываются в фоновом режиме
3
12 февраля 2008 года
Green
4.8K / / 20.01.2000
Цитата: oxotnik333

на форме кнопка "Отмена" в обработчике которой цикл по всем процессам и их завершение


Такое завершение некорректно. Поток не должен завершаться принудительно из вне.
Правильнее проверять в потоках некий объект синхронизации, который устанавливается из основного потока для сигнализации отмены выполнения. Далее основной поток ожидает завершения порожденных.

11
12 февраля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: Green
Такое завершение некорректно. Поток не должен завершаться принудительно из вне.
Правильнее проверять в потоках некий объект синхронизации, который устанавливается из основного потока для сигнализации отмены выполнения. Далее основной поток ожидает завершения порожденных.



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

240
12 февраля 2008 года
aks
2.5K / / 14.07.2006
Это критично в том плане, что убивая поток принудительно - убиваются все данные принадлежащие ему безо всякой деинициализации, освобождения ресурсов и т.п.
11
12 февраля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: aks
Это критично в том плане, что убивая поток принудительно - убиваются все данные принадлежащие ему безо всякой деинициализации, освобождения ресурсов и т.п.



инициализацию/деинициализацию объектов делать вне потока, а в потоке только обрабатывать объекты (ИМХО взял для себя за некое правило)

3
12 февраля 2008 года
Green
4.8K / / 20.01.2000
Цитата: oxotnik333
инициализацию/деинициализацию объектов делать вне потока, а в потоке только обрабатывать объекты (ИМХО взял для себя за некое правило)


Ты передаешь в новый поток имя файла:

 
Код:
DWORD WINAPI CheckFile (LPVOID FileName)
{
  // обработка файла
}

это значит, что файл будет открыт уже в потоке?
Тогда кто его будет закрывать?

Даже если "инициализацию/деинициализацию объектов делать вне потока", что само по себе странно, то все равно ты не сможешь гарантировать освобождение ресурсов занятых потоком, т.к. тогда придется отказаться от использования в потоках каких-либо библиотек (в т.ч. CRT), а так же WinAPI, которые тоже используют ресурсы.
490
12 февраля 2008 года
frid-karatel
357 / / 15.09.2007
Мне главное получить:
1. Структурированные по заданному типу данные
2. Во время выполнения операции статус заверения (в %)
3. Возможность отмены в любое время
11
12 февраля 2008 года
oxotnik333
2.9K / / 03.08.2007
ну вобщем то имелась ввиду следующая конструкция:
Код:
MyObject = new TMyObject;
CreateThread( NULL , 0 , ChangeMyObject, (LPVOID)pParam, 0 , NULL );
//-----------------------
DWORD WINAPI ChangeMyObject  (LPVOID pParam)
{
// какие то операции над MyObject
}
// ----------------------
void CheckThread (m_Thread)
{
  DWORD dwExitCode;
  GetExitCodeThread (m_Thread, &dwExitCode);
  if (dwExitCode != STILL_ACTIVE)
      delete MyObject;
}


PS: в переменную FileName (из 1-го поста) можно передавать не имя файла а его дескриптор (и переименовать ее в handle_file :))
3
12 февраля 2008 года
Green
4.8K / / 20.01.2000
Цитата: oxotnik333
ну вобщем то имелась ввиду следующая конструкция:
Код:
MyObject = new TMyObject;
CreateThread( NULL , 0 , ChangeMyObject, (LPVOID)pParam, 0 , NULL );
//-----------------------
DWORD WINAPI ChangeMyObject  (LPVOID pParam)
{
// какие то операции над MyObject
}
// ----------------------
void CheckThread (m_Thread)
{
  DWORD dwExitCode;
  GetExitCodeThread (m_Thread, &dwExitCode);
  if (dwExitCode != STILL_ACTIVE)
      delete MyObject;
}


При этом ChangeMyObject, если её прерывание является штатным в программе, не может вызывать никаких функций даже из CRT, WinAPI и т.п. Много ли проку от такой функции?

Цитата: oxotnik333

PS: в переменную FileName (из 1-го поста) можно передавать не имя файла а его дескриптор (и переименовать ее в handle_file :))


Опять же, много ли толку от переданного дескриптора? Читать то из файла нельзя, т.к. это вызов ReadFile из WinAPI.

490
12 февраля 2008 года
frid-karatel
357 / / 15.09.2007
Я, наверное, забыл указать, что использую проекцию на файл:
Код:
HANDLE hFileRead = NULL;
  HANDLE hMapFile = NULL;
  LPVOID pMemory = NULL;
  int FileSize;
  __int64 CheckSumm = -1;

  hFileRead = CreateFile(FileName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);
  if (hFileRead != NULL)
  {
    hMapFile = CreateFileMapping(hFileRead, NULL, PAGE_READONLY, 0, 0, NULL);
    if (hMapFile)
    {
      pMemory = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
      FileSize = GetFileSize(hFileRead, 0);
      for (int a = 0; a < FileSize; a++)
      {
        //Делаю необходимое
      }
      UnmapViewOfFile(pMemory);
    }
    CloseHandle(hMapFile);
  }
  CloseHandle(hFileRead);


И лучше всего делать все это в потоке, да?
А сколько можно создать потоков? Как это зависит от типа процессоров и их количества? На что ориентироваться, создавая потоки и сколько их должно быть?
11
12 февраля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: Green
При этом ChangeMyObject, если её прерывание является штатным в программе, не может вызывать никаких функций даже из CRT, WinAPI и т.п. Много ли проку от такой функции?


Опять же, много ли толку от переданного дескриптора? Читать то из файла нельзя, т.к. это вызов ReadFile из WinAPI.



вот такой код работает на ура:

Код:
void __fastcall TForm2::FormShow(TObject *Sender)
{
  CreateThread( NULL , 0 , ChangeForm2, (LPVOID)this, 0 , NULL );
}
//---------------------------------------------------------------------------
DWORD WINAPI ChangeForm2 (LPVOID pForm)
{
  TForm2 *fm = (TForm2*) pForm;
  for (int i=0; i<100; i++)
      {
        fm->ProgressBar1->Position++;
        Sleep(50);
        FindWindow("TForm1", "Form1");

      }


  return 0;
}

и WinAPI вызывается, и объект можно использовать
3
12 февраля 2008 года
Green
4.8K / / 20.01.2000
Цитата: oxotnik333
вот такой код работает на ура:

Код:
void __fastcall TForm2::FormShow(TObject *Sender)
{
  CreateThread( NULL , 0 , ChangeForm2, (LPVOID)this, 0 , NULL );
}
//---------------------------------------------------------------------------
DWORD WINAPI ChangeForm2 (LPVOID pForm)
{
  TForm2 *fm = (TForm2*) pForm;
  for (int i=0; i<100; i++)
      {
        fm->ProgressBar1->Position++;
        Sleep(50);
        FindWindow("TForm1", "Form1");

      }


  return 0;
}

и WinAPI вызывается, и объект можно использовать


Я что-то не вижу в этом коде внешнего завершения потока и проверки освобождения после этого ресурсов. :)
А ресурсы будут аллоцированы в потоке, и большая вероятность, что не освобождены.
Пример: функция FindWindow однозначно аллоцирует, а перед возвращением освобождает внутри себя память. Допустим, поток был прерван при выполнении этой функции. В результате имеем утечку памяти.

Кроме того, где в данном примере синхронизация доступа к объектам, используемым в нескольких потоках?
В частности, строка
fm->ProgressBar1->Position++;
может привести к ошибкам синхронизации.

3
12 февраля 2008 года
Green
4.8K / / 20.01.2000
Цитата: frid-karatel
Я, наверное, забыл указать, что использую проекцию на файл:
Код:
HANDLE hFileRead = NULL;
  HANDLE hMapFile = NULL;
  LPVOID pMemory = NULL;
  int FileSize;
  __int64 CheckSumm = -1;

  hFileRead = CreateFile(FileName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);
  if (hFileRead != NULL)
  {
    hMapFile = CreateFileMapping(hFileRead, NULL, PAGE_READONLY, 0, 0, NULL);
    if (hMapFile)
    {
      pMemory = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
      FileSize = GetFileSize(hFileRead, 0);
      for (int a = 0; a < FileSize; a++)
      {
        //Делаю необходимое
      }
      UnmapViewOfFile(pMemory);
    }
    CloseHandle(hMapFile);
  }
  CloseHandle(hFileRead);


И лучше всего делать все это в потоке, да?
А сколько можно создать потоков? Как это зависит от типа процессоров и их количества? На что ориентироваться, создавая потоки и сколько их должно быть?



Это вполне можно делать в отдельном потоке. Лучше или нет - зависит от специфики задачи.
Потоков лучше создавать не много. Для твоей задачи целесообразно создать всего два: для UI и для бизнес-логики.

11
12 февраля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: Green
Я что-то не вижу в этом коде внешнего завершения потока и проверки освобождения после этого ресурсов. :)
А ресурсы будут аллоцированы в потоке, и большая вероятность, что не освобождены.
Пример: функция FindWindow однозначно аллоцирует, а перед возвращением освобождает внутри себя память. Допустим, поток был прерван при выполнении этой функции. В результате имеем утечку памяти.

Кроме того, где в данном примере синхронизация доступа к объектам, используемым в нескольких потоках?
В частности, строка
fm->ProgressBar1->Position++;
может привести к ошибкам синхронизации.



я не претендую на лавры и овации...
пример был написан за 2 минуты (как в анекдоте: Полковник, выступая с трибуны "т.к. времени мало, буду говорить не думая") только для того что бы показать возможность доступа к объектам и возможности вызова апи-шных ф-ций.
ЗЫ: освобождение памяти, синхронизация и прерывание в данном примере не рассматривается.
ЗЫЗЫ: Я не оспариваю утверждения, что потоки должны синхронизироваться, перед тем как убить поток надо тыщу раз подумать, к чему это может привести, и вообще, что поток из вне не корректно убивать.

3
12 февраля 2008 года
Green
4.8K / / 20.01.2000
Цитата: oxotnik333
только для того что бы показать возможность доступа к объектам и возможности вызова апи-шных ф-ций.


А кто говорил, что они невозможны?

Цитата: oxotnik333

ЗЫ: освобождение памяти, синхронизация и прерывание в данном примере не рассматривается.


А мои замечания были как раз именно по этому поводу.

Цитата: oxotnik333

ЗЫЗЫ: Я не оспариваю утверждения, что потоки должны синхронизироваться, перед тем как убить поток надо тыщу раз подумать, к чему это может привести, и вообще, что поток из вне не корректно убивать.


Отлично, значит, делаем на вывод:
Поток не должен завершаться принудительно из вне.
Правильнее проверять в потоках некий объект синхронизации, который устанавливается из основного потока для сигнализации отмены выполнения. Далее основной поток ожидает завершения порожденных.

490
12 февраля 2008 года
frid-karatel
357 / / 15.09.2007
в данном случае так все и делается, просто нет необходимости выделять память для всего файла (буфера), к тому же буфер из 20 000 000 байт - это немало... в данном случае используется указатель, от которого мы и пляшем, т.е. сами выбираем - char это или unsigned char...
например:

 
Код:
if (((unsigned char*)pMemory)[100] == 0x01)
{
  Form1->Caption = "OK!";
}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог