0 / 0 / 0
Регистрация: 01.03.2013
Сообщений: 9
1

TThread и копирование файлов

01.03.2013, 13:01. Показов 1654. Ответов 18
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день спецы. Пишу достаточно сложную программу, точнее оптимизирую то, что было написано ранее. Необходимо создать поток который будет забирать данные с нескольких ListBox сортировать их на форме. Начну по порядку. Создал простую форму с FileListBox и полем Memo для вывода.
Поток запускаю на главной форме, скажем, кнопкой:
C
1
2
3
4
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Tt1(false);
}
Отдельно создал TThread:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void copy_files(AnsiString FromPath, AnsiString ToPath)
{
CopyFileA(FromPath.c_str(),ToPath.c_str(),false);
}
void __fastcall Tt1::Execute()
{
 NameThreadForDebugging("ThreadM");
 FreeOnTerminate = true;
  for(int i=0; i < Form1->FileListBox1->Count-1; i++)
  {
  if(Terminated) break;
  Synchronize(pb);
  // Критический раздел.
  EnterCriticalSection(&Form1->CS);
  copy_files(Form1->FileListBox1->Directory + "\\" + Form1->FileListBox1->Items->Strings[i],
  "C:\\tmp\\"+Form1->FileListBox1->Items->Strings[i]);
  LeaveCriticalSection(&Form1->CS);
  }
// Синхронизация и вывод что копируется.
void __fastcall Tt1::pb()
{
static int n = 0;
n++;
Form1->Memo1->Lines->Add(Form1->FileListBox1->Directory + "\\" + Form1->FileListBox1->Items->Strings[n]);
Application->ProcessMessages();
}
}
Вообщем-то проблема. Если объявить поток в основном модуле
C
1
Tt1 *Thr = new Tt1(true);
и сразу запустить приостановленным. То первый раз запустить можно будет, повторно нет. Причем даже после того как его убить
C
1
Thr->Terminate();
Что я забыл? Память же должна освободится? Как его корректно завершить?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.03.2013, 13:01
Ответы с готовыми решениями:

Копирование: Ввод имени папки и копирование из нее файлов
Доброго времени суток! Реально ли реализовать подобное с помощью bat ? Знаю, что можно создать...

Копирование файлов из разных каталогов в каталоги с именами, соответствующими номерам в именах файлов
Добрый день! Помогите решить проблему. Есть семь папок (cam_1, cam_2, cam_3 и.т.д) с фотографиями...

Копирование файлов из одной папки в другую, но с пропуском одинаковых файлов в этих папках
Доброго времени суток. Прошу помощи в написании батника. Задача: Есть папка А с файлами 1,2,3 и...

Копирование отсутствующих и изменённых файлов по результатам сверки файлов одного каталога с файлами другого
Всем привет. такая вот задача у меня. я не селен в этом. но стараюсь. есть 2 каталога (1. NEW, 2....

18
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.03.2013, 16:49 2
C++
1
FreeOnTerminate = true;
Зачем это пихать Еxecute() ? есть ведь конструктор!
C++
1
2
3
4
5
  // Критический раздел.
  EnterCriticalSection(&Form1->CS);
  copy_files(Form1->FileListBox1->Directory + "\\" + Form1->FileListBox1->Items->Strings[i],
  "C:\\tmp\\"+Form1->FileListBox1->Items->Strings[i]);
  LeaveCriticalSection(&Form1->CS);
Тут может быть deadlock если будет исключение внутри блока

C++
1
2
3
4
5
6
7
8
// Синхронизация и вывод что копируется.
void __fastcall Tt1::pb()
{
static int n = 0;
n++;
Form1->Memo1->Lines->Add(Form1->FileListBox1->Directory + "\\" + Form1->FileListBox1->Items->Strings[n]);
Application->ProcessMessages();
}
А тут статическая переменная ? Нафига она тут ? Она ж не будет обнуляться при создании нового потока ?

Добавлено через 55 секунд
Цитата Сообщение от Fedor-Builder Посмотреть сообщение
То первый раз запустить можно будет, повторно нет.
Это как ? И почему нет ?
0
0 / 0 / 0
Регистрация: 01.03.2013
Сообщений: 9
01.03.2013, 21:24  [ТС] 3
С первым вопросом, спасибо за подсказку. Можно повешать на кнопку.
C++
1
2
Thr->FreeOnTerminate = True;
Thr->Resume();
Проблема действительно в переменной типа static. Но, как теперь быть с синхронизацией? Если использую просто int число, то получаю вывод только первой строчки. В процедуре Tt1:b() цикл делать тоже? Теперь с запуском все хорошо. Еще раз спасибо за подсказки.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.03.2013, 21:31 4
TThread - это базовый класс а наш класс от него наследуется...
Т.е. и относится мы должны к нему как классу - т.е. можем определять методы и члены класса(поля) в нем ( А инициализировать в его конструкторе, кстати его тоже можно переопределить).
0
0 / 0 / 0
Регистрация: 01.03.2013
Сообщений: 9
01.03.2013, 22:02  [ТС] 5
Немного не понял. Точнее, что передавать в индекс строки чтобы вывести нужную?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.03.2013, 22:13 6
Ну так сделай n членом класса потока в чем проблема ?

Сразу не углядел

C++
1
2
copy_files(Form1->FileListBox1->Directory + "\\" + Form1->FileListBox1->Items->Strings[i],
"C:\\tmp\\"+Form1->FileListBox1->Items->Strings[i]);
Тут опасное обращение к компоненту без синхронизации...
1
0 / 0 / 0
Регистрация: 01.03.2013
Сообщений: 9
02.03.2013, 11:43  [ТС] 7
Здравствуйте.
Не понял почему?
Цитата Сообщение от Avazart Посмотреть сообщение
Тут может быть deadlock если будет исключение внутри блока
С переменно разобрался. Спасибо огромное.
C++
1
2
3
4
5
6
class Tt1 : public TThread
{
protected:
    void __fastcall Execute();
    void __fastcall pb();
    int counts;
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void __fastcall Tt1::Execute()
{
 NameThreadForDebugging("ThreadM");
  for(counts=0; counts < Form1->FileListBox1->Count-1; counts++)
  {
  if(Terminated) break;
  copy_files(Form1->FileListBox1->Directory + "\\" + Form1->FileListBox1->Items->Strings[counts],
  "C:\\tmp\\"+Form1->FileListBox1->Items->Strings[counts]);
  Synchronize(pb);
  }
}
 
void __fastcall Tt1::pb()
{
Form1->Memo1->Lines->Add(Form1->FileListBox1->Directory + "\\" + Form1->FileListBox1->Items->Strings[counts]);
Application->ProcessMessages();
}
Добавлено через 1 час 10 минут
Есть еще проблема с которой не пойму как быть. На форме хочу использовать компонент PageControl. Во вкладках располагать ListBox`ы Memo и т.д. Проблема: не получается выполнить поток повторно.
При повторном вызове потока вылазит окошко "Thread Error: Неверный дескриптор (6)"
Такое происходит только на компоненте PageControl и только при повторном вызове.

Добавлено через 1 час 36 минут
Прошу прощения, за столь глупые вопросы. С последним разобрался. Остается в принципе один важный вопрос, как проверить завершился ли поток? Допустим кнопка выполняет запуск потока, а дальше как отследить, что он завершен, а затем продолжить выполнение следующих действий?
0
Почемучка)
1244 / 304 / 30
Регистрация: 23.12.2010
Сообщений: 2,001
Записей в блоге: 1
02.03.2013, 13:24 8
Fedor-Builder, Почитайте
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.03.2013, 16:02 9
Цитата Сообщение от Fedor-Builder Посмотреть сообщение
Не понял почему?
В
C++
1
2
copy_files(Form1->FileListBox1->Directory + "\\" + Form1->FileListBox1->Items->Strings[i],
"C:\\tmp\\"+Form1->FileListBox1->Items->Strings[i]);
вы обращаетесь к Form1->FileListBox1 без синхронизации ...

Добавлено через 2 минуты
Цитата Сообщение от Fedor-Builder Посмотреть сообщение
Прошу прощения, за столь глупые вопросы. С последним разобрался. Остается в принципе один важный вопрос, как проверить завершился ли поток? Допустим кнопка выполняет запуск потока, а дальше как отследить, что он завершен, а затем продолжить выполнение следующих действий?
Самое простое блокировать кнопку, а потоке ее разблокировать в деструкторе ( естественно с синхронизацией)

А вообще Определить состояние потока TThread

Можно конечно создать в потоке свойство которое будет говорить об окончании и при использовать FreeOnTerminate= false, и поток удалять вручную ...
0
0 / 0 / 0
Регистрация: 01.03.2013
Сообщений: 9
02.03.2013, 23:55  [ТС] 10
Спасибо ребята за поддержку. Более менее разобрался. Хотел спросить, синхронизация нужна во всех случаях чтение записи данных на форме? Если в потоке цикл пытается получить кол-во строк в ListBox например, при этом синхронизация не нужна?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
03.03.2013, 00:02 11
Цитата Сообщение от Fedor-Builder Посмотреть сообщение
Хотел спросить, синхронизация нужна во всех случаях чтение записи данных на форме?
Везде где участвует перерисовка окна...
Цитата Сообщение от Fedor-Builder Посмотреть сообщение
Если в потоке цикл пытается получить кол-во строк в ListBox например, при этом синхронизация не нужна?
Скорее всего нужно вдруг в этот момент пользователь решит удалить или добавить строку ?
Теоретически если только читать то можно без синхронизации, но для этого нужно быть уверенным что во внутренних "механизмах" VCL происходит только чтение ...
1
0 / 0 / 0
Регистрация: 01.03.2013
Сообщений: 9
03.03.2013, 13:34  [ТС] 12
Столкнулся с проблемой ожидания завершения потока на форме. Как бы сделать так, что когда поток закончен вылезла табличка?
C++
1
2
3
My1 *Thr = new My1(true);
Thr->Resume();
if (Thr->Finished == false) ShowMessage("OK");
Может в самом потоке вернуть значение типа true и ждать его че нить. Просто не знаю как правильно.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
03.03.2013, 15:56 13
Цитата Сообщение от Fedor-Builder Посмотреть сообщение
Может в самом потоке вернуть значение типа true и ждать его че нить. Просто не знаю как правильно.
Правильно в самом потоке взвать ShowMessage() перед самым выходом из Execute() ( но стоит заметить что поток не закончится по как вы не нажмете в ShowMessage "OK" ).
0
0 / 0 / 0
Регистрация: 01.03.2013
Сообщений: 9
05.03.2013, 16:56  [ТС] 14
Разобрался. То что мне нужно было реализовал до половины.
Теперь вот, как быть с рекурсивным вызовом функций?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
void FindSUBDir(AnsiString path_from, AnsiString path_dstr, AnsiString fixpath)
{
TSearchRec sr;
if (FindFirst(path_from+"*.*", faAnyFile, sr) == 0)
{
     do
     {
         if (sr.Attr &  faDirectory) // смотрим на директории
          {
              if (sr.Name!=".")
              if (sr.Name!="..")
              {   FindSUBDir(path_from+sr.Name+"\\", path_dstr, fixpath);
              // Рекурсивный  вызов
 
                  AnsiString ansi_string = path_from+sr.Name; // путь к подкаталогу
                  AnsiString ottuda = fixpath; // строка папки LB2
 
                  AnsiString tuda = path_dstr; // куда
                  int ttl = ottuda.Length();
                  int index = ansi_string.Pos(path_from+sr.Name);
                  if( index != 0 ) ansi_string.Delete(index,ttl);
 
                  // создавать папки если таких нет.
                  if( DirectoryExists(tuda) == false ) MkDir(tuda);
                  if( DirectoryExists(tuda+ansi_string) == false )
                    { ForceDirectories(tuda+ansi_string);
                    }
              // тут выполняю синхронизацию с другой функцией которая обращается
              // к vlc
              }
          }
     }
     while  (FindNext(sr) ==  0);
     FindClose(sr);
}
    Application->ProcessMessages();
}
Задача состоит в том, что нужно передавать значения функции, выполнять ее рекурсивно и в ней же еще выполнять синхронизацию с vlc объектами. Проблема вообщем-то только с рекурсивным вызовом. Ну и критические разделы подойдут для блокировки данных в том случаи если необходимо вызвать другой поток в потоке?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
05.03.2013, 17:00 15
Каким образом там оказалось
C++
1
Application->ProcessMessages();
0
0 / 0 / 0
Регистрация: 01.03.2013
Сообщений: 9
05.03.2013, 18:22  [ТС] 16
Честно - не помню. т.к. сейчас интересно, как сделать рекурсивную функцию в потоке. Ничего сообразить не могу. Че-то не то написал
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void findTo (String src)
{
TSearchRec sr;
 if (FindFirst(SourcePath+"*.*", faAnyFile, sr) == 0)
 {
     do
     {
         if (sr.Attr &  faDirectory) // смотрим на директории
          {
              if (sr.Name!=".")
              if (sr.Name!="..")
              {
               findTo(src+sr.Name+"\\");
                           // тут что-то типа...
                           // Какие-то действия в этой папке.
              }
          }
     }
     while  (FindNext(sr) ==  0);
     FindClose(sr);
 }
}
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
05.03.2013, 19:43 17
C++
1
2
   if (sr.Name!=".")
              if (sr.Name!="..")
На
C++
1
   if (sr.Name!="." && sr.Name!="..")
Добавлено через 3 минуты
Цитата Сообщение от Fedor-Builder Посмотреть сообщение
Честно - не помню. т.к. сейчас интересно, как сделать рекурсивную функцию в потоке. Ничего сообразить не могу. Че-то не то написал
А в чем проблема то ? сделай её методом класса потока из него синхронизировано вызывай другой метод который и будет делать :
C++
1
2
// тут выполняю синхронизацию с другой функцией которая обращается
              // к vlc
0
0 / 0 / 0
Регистрация: 01.03.2013
Сообщений: 9
06.03.2013, 13:08  [ТС] 18
Цитата Сообщение от Avazart Посмотреть сообщение
А в чем проблема то ?
Проблема в этом:
Корневой каталог
|-> Подкаталог1
|->Подкаталог подкаталога1
C++
1
findTo(src+sr.Name+"\\");
Нужно зайти в подкаталог и выполнить сортировку в нем... и так до последнего.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
07.03.2013, 15:10 19
Цитата Сообщение от Fedor-Builder Посмотреть сообщение
Нужно зайти в подкаталог и выполнить сортировку в нем... и так до последнего.
Сортировку чего ?
0
07.03.2013, 15:10
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
07.03.2013, 15:10
Помогаю со студенческими работами здесь

Копирование файлов с FTP-сервера на компьютеры клиентов без замены уже имеющихся файлов
Приветствую. Такая задача. имеется фтп сервер. на нем лежит 5 папок, в каждой паке каждый день...

Копирование файлов с переименованием в случае совпадения имён перемещаемых и имеющихся в папке назначения файлов
Добрый день. Помогите создать bat файл. Смысл в чем есть папка загрузки на компьютере с нее файлы и...

Копирование файлов с переименованием в случае совпадения имён копируемых и имеющихся в папке назначения файлов
Доброго времени суток. Убедительная просьба, помогите пожалуйста решить задачу. Существует...

Копирование файлов по списку в текстовом файле в папки с именами, соответствующими расширениям этих файлов
Добрый день, уважаемые форумчане. Прошу помощи с написанием bat-файла. Значит задача такая. Есть...

Копирование файлов в нужные папки, исходя из имён файлов
подскажите, задача примерно аналогичная в папке множество файлов wav, у всех в начале присутствует...

Добавление префиксов к именам файлов и копирование файлов
Доброго времени суток, уважаемые, знатоки! Столкнулся с задачей конвертации большого объема DAV...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru