В вашем коде отсутствует важная деталь, как вы используете TMyThread
класс. Тем не менее, вы пишете
время от времени появляются сайты, на которых файл не будет загружен, но wget или Firefox / IE загрузят его без проблем.
, что звучит как проблема синхронизации.
Использование локальной переменной работает каждый раз. Использование параметра функции работает только некоторое время. Это может быть вызвано тем, что параметр функции не содержит правильный URL , иногда .
Вы должны знать, что создание не приостановленного потока может привести к тому, что он начнет выполняться немедленно (и, возможно, даже завершиться), до следующей строки после того, как вызов конструкции даже начал выполняться. Поэтому установка любого свойства объекта потока после того, как поток был создан, может не сработать, так как выполнение потока может быть после точки, в которой свойство читается. Поле fTheUrl
объекта потока изначально будет пустой строкой, поэтому то, будет ли поток загружать файл, будет зависеть от того, был ли он установлен ранее.
Ваше поле fTheUrl
даже не защищено примитивом синхронизации. И процесс потока, и код в основном потоке могут получить к нему доступ одновременно. Распределение данных между потоками таким способом небезопасно и может привести к любой вещи - от неправильного поведения до реальных сбоев.
Если ваш поток действительно используется для загрузки одного файла, вы должны удалить доступ на запись к свойству и написать собственный конструктор с параметром для URL. Это правильно инициализирует поле перед началом потока.
Если вы загружаете несколько файлов в своей программе, вам не следует создавать поток для каждого. Используйте пул потоков (может быть только один), которым будут назначены файлы для загрузки. Для этого свойство потока является правильным решением, но тогда оно должно быть реализовано с синхронизацией, и поток должен блокироваться, когда файл не должен быть загружен, и разблокироваться, когда свойство установлено. Поток загрузки (или потоки) будет потребителем (ями) в реализации производитель-потребитель. Stack Overflow содержит вопросы и ответы по этому поводу в теге Delphi, в частности, в вопросах, где обсуждаются альтернативы Suspend()
и Resume()
.
И последнее: не позволяйте необработанным исключениям избегать метода Execute()
. Я не уверен, обрабатывает ли Delphi 2010 эти исключения в VCL, но необработанные исключения в потоке могут привести к таким проблемам, как сбой или зависание приложения.