Вопрос, поднятый в контексте, связан с обработкой потоков в среде разработки Delphi XE7. Пользователь столкнулся с исключением, возникающим при попытке создания потока в проекте. Код, представленный в запросе, содержит определение класса TURLDownload, наследующегося от TThread, а также основную форму TForm1 с кнопкой Button1, клик по которой должен запустить поток.
Оригинальный заголовок:
Почему при создании потока возникает исключение?
Описание проблемы (вопрос):
При нажатии на кнопку Button1 для запуска потока возникает исключение. В сообщении об ошибке упоминается "access violation", что указывает на попытку доступа к неинициализированной памяти. Это часто происходит, когда программа пытается прочитать или записать данные в область памяти, которая не была выделена или не была корректно инициализирована.
Код, вызывающий ошибку:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
TURLDownload = class(TThread)
private
FURL: String;
Fnameofimg: string;
FPathImage: string;
FFileNameImage: string;
// Internal //
ImageName: string;
PathURL: string;
protected
procedure Execute; override;
public
constructor Create(const AUrl: String; Const AOutPathImages: string;
Anameofimg: String); reintroduce;
destructor Destroy; override;
property URL: string read FURL write FURL;
property PathImage: string read FPathImage;
property FileNameImage: string read FFileNameImage;
end;
var
Form1: TForm1;
th: TURLDownload;
implementation
{$R *.dfm}
// Остальной код класса TURLDownload и реализация формы Form1
procedure TForm1.Button1Click(Sender: TObject);
begin
th.Create('jgvjk', 'ngkj', 'jkgfjk'); // Ошибка здесь
end;
end.
Сообщение об исключении:
First chance exception at $004C0384. Exception class $C0000005 with message 'access violation at 0x004c0384: read of address 0x0000003c'. Process Project1.exe (4060)
Подробности исключения:
При нажатии на перерыв, отладчик возвращает к файлу System.Classes, внутри функции Thread.Create, на строку, где происходит установка флага FSuspended:
FSuspended := not FExternalThread;
Подтвержденный ответ:
Проблема заключается в том, что объект потока не создается корректно. Вместо этого вызывается конструктор класса TURLDownload напрямую, без создания нового экземпляра. Исправленный код должен выглядеть следующим образом:
procedure TForm1.Button1Click(Sender: TObject);
begin
th := TURLDownload.Create('jgvjk', 'ngkj', 'jkgfjk'); // Создание объекта потока
end;
Также стоит отметить, что в теле потока используется вызов ShowMessage, который взаимодействует с VCL-компонентами, и это должно быть сделано с использованием Synchronize, чтобы избежать блокировки основного потока.
Альтернативный ответ:
Кроме того, в коде есть несколько моментов, которые можно улучшить:
Слово reintroduce не требуется для конструктора, который не является виртуальным.
В методе Execute вызов inherited не выполняет никаких действий, так как метод пуст.
Пример кода с исправлениями:
constructor TURLDownload.Create(const AUrl, AOutPathImages: string; Anameofimg: String);
begin
inherited Create(False); // Удаляем параметр 'False', так как он не используется
FreeOnTerminate := True;
FURL := AUrl;
Fnameofimg := Anameofimg;
FPathImage := AOutPathImages;
end;
procedure TURLDownload.Execute;
begin
Synchronize(procedure
begin
ShowMessage('Завершено');
end
);
end;
Комментарий:
Даже с использованием Synchronize, необходимо убедиться, что все операции с VCL-компонентами в потоке выполнены корректно, чтобы избежать исключений, связанных с доступом к неинициализированным ресурсам и блокировками потока.
При работе с потоками в Delphi важно помнить о правилах безопасности многопоточности и корректно обрабатывать взаимодействие между потоками и VCL-компонентами.
Контекст: Пользователь столкнулся с исключением при попытке создать поток в среде разработки Delphi XE7, связанным с неправильной инициализацией объекта потока и попыткой доступа к неинициализированной памяти.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.