C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
как избавится от тормозов
joynter
Отправлено: 04.11.2004, 14:21


Станционный диспетчер

Группа: Участник
Сообщений: 137



моя прога копирует файлы и при этом на форме нельзя нажать какую-либо кнопку, передвинуть саму форму и тд.
как от этого можно избавится?
Doga
Отправлено: 04.11.2004, 14:32


Мастер участка

Группа: Участник
Сообщений: 575



Либо создать отдельный поток (TThread), либо использовать ProcessMessages()
joynter
Отправлено: 04.11.2004, 15:20


Станционный диспетчер

Группа: Участник
Сообщений: 137



спасибо за подсказку, но с Application->ProcessMessages()
все равно есть некоторые тормоза во время копирования.
Не могли бы уважаемые господа программисты
просветить меня на тему:
а что есть TThread ( у меня в хелпе вылезло link not found) и как его использовать?
Doga
Отправлено: 04.11.2004, 16:31


Мастер участка

Группа: Участник
Сообщений: 575



QUOTE

TThread is an abstract class that enables creation of separate threads of execution in an application.

Unit

Classes

Description

Create a descendant of TThread to represent an execution thread in a multi-threaded application. Each new instance of a TThread descendant is a new thread of execution. Multiple instances of a TThread derived class make a C++Builder application multi-threaded.

When an application is run, it is loaded into memory ready for execution. At this point it becomes a process containing one or more threads that contain the data, code and other system resources for the program. A thread executes one part of an application and is allocated CPU time by the operating system. All threads of a process share the same address space and can access the process’s global variables.

Use threads to improve application performance by

Managing input from several communication devices.
Distinguishing among tasks of varying priority. For example, a high priority thread handles time critical tasks, and a low priority thread performs other tasks.

Following are issues and recommendations to be aware of when using threads:

Keeping track of too many threads consumes CPU time; the recommended limit is 16 active threads per process on single processor systems.
When multiple threads update the same resources, they must be synchronized to avoid conflicts.
Most methods that access a VCL object and update a form must only be called from within the main VCL thread or use a synchronization object such as TMultiReadExclusiveWriteSynchronizer.

To create and use a new thread object:

Choose File | New | Other | Thread Object to create a new unit that contains an object derived from the TThread class.
Define the new thread object’s constructor.
Define the thread object’s Execute method by inserting the code that should execute when the thread is executed.

Note: See the Threads demo for multi-threading program samples.

Warning: Exceptions that are raised but not caught in the TThread descendant’s Execute method may cause access violations when you run the application outside of the IDE. You can guard against this access violation by providing the Execute method with a try.._finally block that includes the body of that method.


Если Help не находит ключевое слово "TThread" — значит у Вас неполный хелп biggrin.gif . Где его найти — см. тему "Полный английский Хелп". Примеры как с ним (TThread) работать есть в каталоге $(BCB)\Examples

А ещё можно здесь посмотреть:

https://rxlib.ru/forums/index.php?ac...c77fc54ef2fc148

https://rxlib.ru/forums/index.php?ac...c77fc54ef2fc148

Или сами можете поискать побольше... smile.gif

Отредактировано Doga — 04/11/2004, 17:49
joynter
Отправлено: 04.11.2004, 18:32


Станционный диспетчер

Группа: Участник
Сообщений: 137



извините за назойливость, но не могли бы Вы меня поправить:
к своему приложению я присовокупил такой Тhread Object
Unit1.cpp
CODE

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "VCDUnit1.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------

// Important: Methods and properties of objects in VCL can only be
// used in a method called using Synchronize, for example:
//
// Synchronize(UpdateCaption);
//
// where UpdateCaption could look like:
//
// void __fastcall ThreadCopyDir::UpdateCaption()
// {
// Form1->Caption = "Updated in a thread";
// }
//---------------------------------------------------------------------------

__fastcall ThreadCopyDir::ThreadCopyDir(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall ThreadCopyDir::Execute()
{
//---- Place thread code here ----
Synchronize(newStream(sFrom,sTo));
}
//---------------------------------------------------------------------------
void __fastcall ThreadCopyDir::newStream(AnsiString dirFrom, AnsiString dirTo)
{

dirFrom += "\";
dirTo += "\";
TSearchRec sr;
if(!FindFirst(dirFrom + "*.*",faAnyFile | faDirectory, sr));
do
{
if((sr.Name != ".")&&(sr.Name != ".."))
if((sr.Attr&faDirectory) || (sr.Attr == faDirectory))
{
if(!CreateDir(dirTo + sr.Name))
ShowMessage("Не могу создать директорию " + dirTo + sr.Name);
newStream(dirFrom + sr.Name,dirTo + sr.Name);
}
else
{
if(!CopyFile((dirFrom + sr.Name).c_str(),(dirTo + sr.Name).c_str(),0))
ShowMessage("Не могу скопировать " + dirTo + sr.Name);
else
Form1->ListBox2->Items->Add(dirTo + sr.Name);
//Application->ProcessMessages();
}
}
while(!FindNext(sr));
FindClose(sr);
}

Unit1.h
CODE

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
//---------------------------------------------------------------------------
class ThreadCopyDir : public TThread
{
private:
void __fastcall newStream(AnsiString sFrom, AnsiString sTo);
protected:
void __fastcall Execute();
public:
__fastcall ThreadCopyDir(bool CreateSuspended);
AnsiString sFrom,sTo;
};
//---------------------------------------------------------------------------
#endif


в файле VCDUniy1.cpp вызов происходит так
CODE

...
#include "VCDUnit1.h"
#include "Unit1.h"
...
String sFrom = ComboBox1->Text,
sTo = diskFullName;
//CopyDir(sFrom,sTo);
ThreadCopyDir *newProcess = new ThreadCopyDir(true);

но при компиляции появляются такие ошибки:
CODE

[C++ Error] Unit1.cpp(32): E2468 Value of type void is not allowed
[C++ Error] Unit1.cpp(32): E2342 Type mismatch in parameter 'Method' (wanted 'void (_fastcall * (_closure )())()', got 'void')

что я делаю не так?

Отредактировано joynter — 05/11/2004, 10:52
Doga
Отправлено: 04.11.2004, 19:23


Мастер участка

Группа: Участник
Сообщений: 575



Параметром метода Synchronize может быть только метод типа:

void __fastcall ThreadCopyDir::newStream(void)

Данные необходимые для метода newStream следует передавать через члены класса ThreadCopyDir. Т.е. AnsiString sFrom и AnsiString sTo должны быть обьявлены в этом классе, а инициализировать их можно например в конструкторе ThreadCopyDir.

Вызов для вашего случая должен выглядеть так:

Synchronize(newStream);


Вобще Synchronize можно и не использовать, если поток работает втихую и ничего на экран не выводит smile.gif

Еще мне кажется что вы изобретаете очередной велосипед (заранее извиняюсь, если это не так smile.gif ) В WinAPI есть универсальная процедура для таких случаев :

SHFileOperation

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

Надо только её правильно настроить biggrin.gif

Если не разберётесь — могу выложить примерчики

Есть ещё в библиотеке RXLib есть функция CopyFile. с подключением
в качестве индикатора копирования TGauge или TProgressBar

procedure CopyFile(const FileName, DestName: string; ProgressControl: TControl);


Тут на форуме эта тема (про копирование, удаление...) поднималась много раз — можете Сами поискать ежели что...

Удачи smile.gif
joynter
Отправлено: 05.11.2004, 10:25


Станционный диспетчер

Группа: Участник
Сообщений: 137



спасибо. со многопоточностью я разобрался. конечно удобнее пользоваться РХ-компонентами, но мне хотелось все-таки узнать как оно работает. а по поводу SHFileOperation — это первое, что я пробовал, но там есть одна неувязочка — удалять директории можно, а копировать не получается, тк pFrom должен быть файлом, а pTo — директорией (по крайней мере так в хелпе).
pagan
Отправлено: 05.11.2004, 12:15


Ученик-кочегар

Группа: Участник
Сообщений: 22



QUOTE
void __fastcall ThreadCopyDir::Execute()
{
      //---- Place thread code here ----
      Synchronize(newStream(sFrom,sTo));
}
//---------------------------------------------------------------------------

Честно говоря в методе Execute() как раз таки должен содержаться код, который будет выполняться потоком. Метод Syncronize же синхронизирует ваш поток с основным. Т.е как такового потока здесь у вас не получается.
Gedeon
Отправлено: 05.11.2004, 12:31


Ветеран

Группа: Модератор
Сообщений: 1742



QUOTE (joynter @ 05/11/2004, 11:27)
а по поводу SHFileOperation — это первое, что я пробовал, но там есть одна неувязочка — удалять директории можно, а копировать не получается, тк pFrom должен быть файлом, а pTo — директорией (по крайней мере так в хелпе).

Вот Вам пример
CODE

bool CopyDir(const char *From, const char *To, bool ShowErrorOnFail)
{
   char *IFrom;                            //строка пути должна заканчиваться
   IFrom = (char*)malloc(lstrlen(From)+2); //двумя нулями, что и делается в
   strcpy(IFrom,From);                     //первых четырех строках т.е.
   IFrom[lstrlen(IFrom)+1]='\0';           //добавляется еще 1 '\0'

   char *ITo;                              //строка пути должна заканчиваться
   ITo = (char*)malloc(lstrlen(To)+2);     //двумя нулями, что и делается в
   strcpy(ITo,To);                         //первых четырех строках т.е.
   ITo[lstrlen(ITo)+1]='\0';               //добавляется еще 1 '\0'

   if(!IsDir(To)){                         //если папка назначения не
       SECURITY_ATTRIBUTES sa;             //существует, создаем ее
       sa.nLength = sizeof(SECURITY_ATTRIBUTES);
       sa.lpSecurityDescriptor = NULL;
       sa.bInheritHandle = false;
       CreateDirectory(To,&sa);
   }

   SHFILEOPSTRUCT strFileOp;               //заполняем параметры структуры
   strFileOp.hwnd = NULL;
   strFileOp.wFunc = FO_COPY;
   strFileOp.pFrom = IFrom;
   strFileOp.pTo = ITo;

   if(!ShowErrorOnFail) strFileOp.fFlags = FOF_NOCONFIRMATION|FOF_NOERRORUI;
   else strFileOp.fFlags = FOF_NOCONFIRMATION;

   if(!SHFileOperation(&strFileOp)) return false;
   free(IFrom);
   free(ITo);
   return true;
}
//----------------------------------------------------------------------------

IsDir — моя функция для проверки существования папки.
Можете вместо входных char* использовать AnsiString тогда попроще будет.
joynter
Отправлено: 05.11.2004, 13:44


Станционный диспетчер

Группа: Участник
Сообщений: 137



спасибо за пример.
теперь другой естественный вопрос вскакивает:
если имеется многопоточное приложение, то как запретить юзеру его закрыть во время выполнения вторичного потока?
Doga
Отправлено: 05.11.2004, 14:23


Мастер участка

Группа: Участник
Сообщений: 575



Я думаю что вопрос поставлен некорректно.

Что если юзер хочет закрыть приложение по причине нежелания дальнейшей работы вторичного потока? Т.е. он просто желает завершить работу вторичного потока?

Не стоит запрещать пользователю делать то что он хочет. Ему это не понравится. Однозначно biggrin.gif

Но если без этого нельзя — проблема решается написанием обработчика события OnCloseQuery smile.gif

Вернуться в Вопросы программирования в C++Builder