Модераторы: Snowy, Poseidon, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> поток отрабатывает, при закрытии программы ошибка, 1400. Недопустимый дескриптор окна 
:(
    Опции темы
firs70
Дата 27.6.2007, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 12.2.2007

Репутация: нет
Всего: нет



Сделал Uploader для FileFactory и RapidShare. процессы загрузки файлов на сервер сделал в отдельных потоках, сами потоки практически эдентичны. При отработки потока для FileFactory закрываю программку без ошибок, после отработки потока для RapidShare при закрытии программки вылетает сообщение "ошибка 1400 Недопустимый дескриптор окна"

Использую для запросов дополнительный модуль HTTPSend пусть это вас не смущает.

вызываю поток вот так:
Код

procedure TForm1.Button9Click(Sender: TObject);   // кнопка "загрузить"
begin
 Edit6.Clear;   // очистка поля для ссылки на загруженный файл
 if Form1.Edit5.Text='' then ShowMessage('Выберите Файл!!!') else  // в Эдит5 находится путь до файла который загружаем
 begin
 ZRThread.Create(False);  // запуск потока   
 end;
end;


Сам поток вот:
Код

unit ZRapid;

interface

uses
 Classes, MrMax,
  HTTPSend,                 // Для доступа через прокси;
   Windows, Messages, SysUtils, Variants, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, Wininet;
type
 ZRThread = class(TThread)
  private
  protected
   procedure Execute; override;
   end;

implementation

uses  Unit1;

//===============================================
function ProxyHttpPostFile1(const URL, FieldName, FileName: string;
  const Data: TStream; const ResultData: TStrings): Boolean;
const
  CRLF = #$0D + #$0A;
var
  HTTP: THTTPSend;
  Bound1, s1, host1: string;
begin
  IntToHex(Random(MaxInt), 15);
  Bound1 := IntToHex(Random(MaxInt), 15);
  HTTP := THTTPSend.Create;
    try
     if Form1.CProxy.Checked=True then
      begin
        HTTP.ProxyHost := Form1.EProxy.Text;
        HTTP.ProxyPort := Form1.EPort.Text;
         if Form1.CAuthorization.Checked=True then
         begin
           HTTP.ProxyUser := Form1.ELogin.Text;
           HTTP.ProxyPass := Form1.EPass.Text;
         end;
      end;
     HTTP.HTTPMethod('get', 'http://rapidshare.com/cgi-bin/rsapi.cgi?sub=nextuploadserver_v1');
     form1.Memo4.Lines.LoadFromStream(HTTP.Document);
     host1:=form1.Memo4.Text;
     HTTP.Document.Clear;
     HTTP.Headers.Clear;

    s1 := '----------' + Bound1 + CRLF;
//-----------------
    s1 := s1 + 'Content-Disposition: form-data; name="rsapi_v1"'+ CRLF + CRLF;
    s1 := s1 + '1' + CRLF;
    s1 := s1 + '----------' + Bound1 + CRLF;
//-------------------
     If (Form1.ComboBox2.Text<>'') and (Form1.Edit3.Text<>'')then
     begin
//-----------------
    s1 := s1 + 'Content-Disposition: form-data; name="'+Flag+'"'+ CRLF + CRLF;
    s1 := s1 + Form1.ComboBox1.Text + CRLF;
    s1 := s1 + '----------' + Bound1 + CRLF;
    s1 := s1 + 'Content-Disposition: form-data; name="password"'+ CRLF + CRLF;
    s1 := s1 + Form1.Edit4.Text + CRLF;
    s1 := s1 + '----------' + Bound1 + CRLF;
//-------------------
     end;
    s1 := s1 + 'content-disposition: form-data; name="' + FieldName + '";';
    s1 := s1 + ' filename="' + FileName +'"' + CRLF;
    s1 := s1 + 'Content-Type: application/octet-stream' + CRLF + CRLF;
    HTTP.Document.Write(Pointer(s1)^, Length(s1));
    HTTP.Document.CopyFrom(Data, 0);
    s1 := CRLF + '----------' + Bound1 + '--' + CRLF;
    HTTP.Document.Write(Pointer(s1)^, Length(s1));
    HTTP.MimeType := 'multipart/form-data; boundary=----------' + Bound1;
    Result := HTTP.HTTPMethod('POST', 'http://rs'+host1+'l3.rapidshare.com/cgi-bin/upload.cgi');
    ResultData.LoadFromStream(HTTP.Document);
  finally
    HTTP.Free;
  end;
end;

//=================================================
procedure ZRThread.Execute;
var
st1: TFileStream;
HTTP: THTTPSend;
begin
 Form1.Button9.Enabled:=false;
 Form1.Button10.Enabled:=False;
     st1 := TFileStream.Create(Form1.Edit5.Text, fmOpenRead    or fmShareDenyWrite);
     try
      ProxyHTTPPostFile1('http://www.rapidshare.com/', 'filecontent', ExtractFilename(Form1.Edit5.Text), st1, TStringList(Form1.memo4.Lines));
     finally
     st1.Free;
     end;
      if Form1.Memo4.Text='' then
     begin
      Form1.Edit6.Text:='Не верный формат файла  или нет ответа от Сервера';
      Form1.Button10.Enabled:=False;
      Form1.Button9.Enabled:=True;
     end else
          begin
           Form1.Edit6.Text:=Pars0(Form1.Memo4.Text,'File1.1=',False,#13#10);
           Form1.Button9.Enabled:=True;
           Form1.Button10.Enabled:=True;
          end;  
end;
end.

везде где можно приписал к переменным 1 думал может перекрываются в потоках как-нибудь.. но тлку мало.

Если то что в потоке вставляю в буттон клик всё работает без сбоев и закрывается без ошибки, но прога подвисает сильно

исходник прикрепляю может кто захочет полный код посмотреть - Вот он

Это сообщение отредактировал(а) firs70 - 27.6.2007, 15:19
PM MAIL   Вверх
dumb
Дата 27.6.2007, 15:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 5
Всего: 158



в потоках нельзя напрямую обращаться к формам!

читать Многопоточность - как это делается в Дельфи до полного просветления.
PM MAIL   Вверх
firs70
Дата 28.6.2007, 08:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 12.2.2007

Репутация: нет
Всего: нет



Обращение к формам я думал что это когда к вылетающему сообщению об ощибке, например.
То есть в потоках надо везде где есть обращение к формам дописоывать Synchronize()?
и как правильно
так 
Код

Synchronize(HTTP.ProxyHost := Form1.EProxy.Text);

или так
Код

HTTP.ProxyHost := Synchronize(Form1.EProxy.Text);

PM MAIL   Вверх
MetalFan
Дата 28.6.2007, 08:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 14
Всего: 128



Цитата(firs70 @  28.6.2007,  09:16 Найти цитируемый пост)
ак 
Выделить всёкод Pascal/Delphi
1:
    
Synchronize(HTTP.ProxyHost := Form1.EProxy.Text);

или так
Выделить всёкод Pascal/Delphi
1:
    
HTTP.ProxyHost := Synchronize(Form1.EProxy.Text);

никак не правильно
читать текст по ссылке, данной ранее, еще раз... и еще раз... для полного просвещения.


Это сообщение отредактировал(а) MetalFan - 28.6.2007, 08:51


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
firs70
Дата 28.6.2007, 09:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 12.2.2007

Репутация: нет
Всего: нет



ну ребят подскажите плиз.
тот пример который в статье:
Код

==========================
procedure TPrimeThrd.UpdateResults;
begin
  PrimeFrm.ResultsMemo.Lines.Add(FResultString);
end;

function TPrimeThrd.IsPrime: boolean; {omitted for brevity}

  procedure TPrimeThrd.Execute;
  begin
    if IsPrime then
      FResultString := IntToStr(FTestNumber) + ' is prime.'
    else
      FResultString := IntToStr(FTestNumber) + ' is not prime.';
    Synchronize(UpdateResults);
  end;
=======================

мне не понятен, вернее понятен, НО не могу ладу дать как его применять в моём коде.
если не трудно код подредактируйте мой.
 smile 
PM MAIL   Вверх
MetalFan
Дата 28.6.2007, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 14
Всего: 128



firs70, с программированием на делфи видимо не дружишь.
посмотреть, что принимает в виде параметра метод Synchonize не судьба?
оформи код, который будет выполнятся в осн.потоке в отдельном методе без параметров и передавай его в Synchonize


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
firs70
Дата 28.6.2007, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 12.2.2007

Репутация: нет
Всего: нет



MetalFan , пытаюсь подружиться smile
То есть мне надо переделать код так как будто бы он выполнялся по нажатию бутона (всё в одно засунуть)
и потом прописать 
Код

procedure ZRThread.Execute;
begin
 Synchonize(название процедуры);
end;

или как то по другому?
PM MAIL   Вверх
MetalFan
Дата 28.6.2007, 14:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 14
Всего: 128



Цитата(firs70 @  28.6.2007,  15:34 Найти цитируемый пост)
То есть мне надо переделать код так как будто бы он выполнялся по нажатию бутона (всё в одно засунуть)
и потом прописать 

о мой моск  smile 

рано тебе еше с потоками работать...
подучи сначала Object Pascal smile





--------------------
There are always someone smarter than you...
PM MAIL   Вверх
firs70
Дата 28.6.2007, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 12.2.2007

Репутация: нет
Всего: нет



ну подскажите примером, плиз, неужели так сложно? если шаришь помоему не сложно это.
А так только время тратите что бы меня тут высмеивать smile если бы я всё это знал бы, то не спрашивал - ведь верно?  smile 
PM MAIL   Вверх
Петрович
Дата 17.7.2007, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1000
Регистрация: 2.12.2003
Где: Москва

Репутация: 1
Всего: 55



Мдя.
Типичные проблемы новичков в многопоточном программировании. :(
Во первых, действительно крайне рекомендую прочесть статью ссылку на которую уже приводили выше. Если с первого раза что-то будет непонятно, перечитывай еще, еще, и еще.

Ну а так, что касается конкретно твоего примера: 
Во первых: 
ВАЖНЕЙШЕЕ правило многопоточного программирования на Delphi:
В контексте не основного потока нельзя, обращаться к свойствам и методам форм, да и вообще всех компонентов которые "растут" из tWinControl.

Это означает (несколько упрощенно) что ни в методе Execute унаследованного от TThread, ни в других методах/процедурах/функциях вызываемых из Execute, нельзя напрямую обращаться ни к каким свойствам и методам визуальных компонентов.

А что имеем у тебя - почти в каждой строке обращение к визуальным объектам лежащим на форме Form1.

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

Если коротенько на пальцах:

Чаще всего, многопоточным приложение становится либо когда надо делать какую либо длительную работу, либо когда можно одновременно делать несколько дел, не сильно нагружающих процессор.

В первом случае, реализация работы внутри основного потока приводит к «торможению» пользовательского интерфейса – пока делается работа, не выполняется цикл обработки сообщений. Как следствие – программа не реагирует на действия пользователя, и не прорисовывается форма, например после ее перемещения пользователем.

Во втором случае, когда работа подразумевает активный обмен с внешним миром, то во время вынужденных «простоев». В ожидании получения/отправки данных, можно параллельно делать еще что-то, например, опять же другие посылать/принимать данные.

Существуют и другие случаи, но реже. Впрочем, это и не важно. Сейчас не об этом.

Теперь, как все это пишется. Естественно рассматривается некий наиболее частый случай, несколько обобщенный. Итак.

Работа, выносимая в отдельный поток, в общем случае имеет четыре сущности (уж и не знаю как назвать точнее):
1.    Исходные данные
2.    Собственно сама работа (она может зависеть от исходных данных)
3.    Промежуточные данные (например, информация о текущем состоянии выполнения работы)
4.    Выходные данные (результат)

Чаще всего для считывания и вывода большей части данных используются визуальные компоненты. Но, как было сказано выше – нельзя из потока напрямую обращаться к визуальным компонентам. Как же быть?
Разработчики Delphi предлагают использовать метод Synchronize класса TThread. Здесь я не буду описывать то, как его применять – для этого есть вышеупомянутая статья. Скажу лишь, что его применение, даже правильное, не всегда оправдано. Имеются две проблемы:

Во первых, тело метода вызванного через Synchronize всегда выполняется в контексте основного потока, и поэтому, пока оно выполняется, опять же не выполняется цикл обработки оконных сообщений.  Следовательно, оно должно выполняться быстро, иначе, мы получим все те же проблемы что и при однопоточной реализации. В идеале, метод вызываемый через Synchronize вообще должен использоваться только для обращения к свойствам и методам визуальных объектов.

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

Причем, обе проблемы взаимосвязаны, и вызывают противоречие: с одной стороны, для решения первой, надо «размельчать» методы вызываемые через Synchronize, а с другой, их тогда чаще приходится вызывать, теряя драгоценный процессорный ресурс.

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

Исходные данные
Все данные которые передаются в поток, и не изменяются во время его работы, нужно передавать еще до его запуска, т.е. при создании потока. Для их использования в теле потока, нужно сделать их локальную копию (обычно в полях потомка TThread).
Если есть исходные данные которые могут меняться во время работы потока, то доступ к таким данным нужно осуществлять либо через синхронизируемые методы (методы вызываемые через Synchronize), либо через поля объекта-потока (потомка TThread). Последнее требует определенной осторожности.

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

Эх. Коротенько опять не получилось smile
Попозже, приведу небольшой пример. Требуется время на его подготовку. smile



--------------------
Все знать невозможно, но хочется
PM ICQ   Вверх
Петрович
Дата 17.7.2007, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1000
Регистрация: 2.12.2003
Где: Москва

Репутация: 1
Всего: 55



Ну вот. Обещанный пример изваял и поместил как отдельную тему Пример простого многопоточного приложения
Ежели что опять будет непонятно - пиши(те).


--------------------
Все знать невозможно, но хочется
PM ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Сети"
Snowy
Poseidon
MetalFan

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0895 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.