Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.05.04;
Скачать: CL | DM;

Вниз

Ошибка AV в потоке   Найти похожие ветки 

 
DelphiN! ©   (2008-04-07 14:30) [0]

Пытаюсь отправить данные в потоке, однако иногда при обращении к параметру передаваемому в поток возникает исключение Access Violation. Вот код создания потока и самого потока, отправляющего данные через сокет :


type
 TSendStreamParam = record
   Socket: TCustomWinSocket;
   Stream: TStream;
 end;
var
 SendStreamParam: TSendStreamParam;
 SendStreamCriticalSection: TCriticalSection;

 
function TDATA.SendStream(var Socket: TCustomWinSocket; Stream: TStream): Boolean;
 procedure Send(Par: Pointer);
 var
   i: integer;
   buff: array[0..65536] of byte;
   p: ^TSendStreamParam;
 begin
   try
     SendStreamCriticalSection.Enter;
     try
       p := Par;
       p.Stream.Position:=0; Access violation возникает тут
       repeat
         i:=p.Stream.Read(buff,SizeOf(buff));
         while p.Socket.SendBuf(buff,i)=-1 do
       until i=0;
       p.Stream.Free;
       p.Socket.Close;
       //p.Socket.Free;
     except
       //
     end;
   finally
     SendStreamCriticalSection.Leave;
   end;
 end;
var
 c: Cardinal;
begin
 SendStreamParam.Socket := Socket;
 SendStreamParam.Stream := Stream;
 BeginThread(nil,SizeOf(SendStreamParam),@Send,@SendStreamParam,0,c);
end;


В чем может быть дело?


 
Игорь Шевченко ©   (2008-04-07 14:32) [1]


> В чем может быть дело?


Невложенную процедуру не пробовал ?


 
Сергей М. ©   (2008-04-07 14:34) [2]


> BeginThread(nil,SizeOf(SendStreamParam)


Сам-то понял что сотворил ?


 
Palladin ©   (2008-04-07 15:05) [3]

:)


 
Anatoly Podgoretsky ©   (2008-04-07 16:38) [4]

> Palladin  (07.04.2008 15:05:03)  [3]

:-(
Все по старому, как и пару лет назад.


 
_DATA_   (2008-04-08 09:36) [5]


> Сергей М. ©   (07.04.08 14:34) [2]
>
>
> > BeginThread(nil,SizeOf(SendStreamParam)
>
>
> Сам-то понял что сотворил ?


Определил размер передаваемой в дочерний поток переменной, а как иначе и что не так?

Всплыла еще одна проблема, в дочернем потоке я делаю Socket.Close, однако процедура SendStream с одним и тем-же сокетом вызывается несколько раз из одного и того-же потока, но на второй раз сокет уже закрыт, как решить и эту проблему? Может быть можно как-то открыть закрытый сокет? Решение: закрывать сокет только при последнем вызове потока с одним и тем же сокетом не пойдёт ...


> Игорь Шевченко ©   (07.04.08 14:32) [1]
>
> Невложенную процедуру не пробовал ?


Пробовал, результат тот-же ...


 
_DATA_   (2008-04-08 09:37) [6]


> _DATA_   (08.04.08 09:36) [5]


Ник не тот в браузере стоял, я DelphiN! :-)


 
Сергей М. ©   (2008-04-08 10:04) [7]


> Определил размер передаваемой в дочерний поток переменной,
>  а как иначе и что не так?


2-й параметр - это размер стека треда !


 
Palladin ©   (2008-04-08 10:04) [8]


> Определил размер передаваемой в дочерний поток переменной,
>  а как иначе и что не так?

да ты что... :) кто тебя научил такому?


 
Сергей М. ©   (2008-04-08 10:06) [9]


> в дочернем потоке


За каким лешим нужно плодить потоки, если TServerSocket в режиме thread-blocking и так уже обслуживает каждого активного клиента в отдельном потоке ?


> процедура SendStream


Чем штатный метод SendStream не угодил ?


 
DelphiN!   (2008-04-08 10:08) [10]

Простите грешного :) Установил размер стека статически ... А можно ли определять какой размер стека мне нужен динамически?


 
Сергей М. ©   (2008-04-08 10:10) [11]


> можно ли определять какой размер стека мне нужен динамически?


Это зависит от многих факторов.

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


 
DelphiN!   (2008-04-08 10:11) [12]


> Сергей М. ©   (08.04.08 10:06) [9]


TServerSocket в режиме stNonBlocking, а обслуживать каждого активного клиента в отдельном потоке не могу, так как при обработке использую компоненты IBX и СУБД FireBird которые отказываются "правильно" работать в отдельных потоках


 
Сергей М. ©   (2008-04-08 10:13) [13]


> компоненты IBX и СУБД FireBird которые отказываются "правильно"
> работать в отдельных потоках
>


Ды ты что ?!

Неужели прямо так и говорят - "Отказываемся" ?)


 
DelphiN!   (2008-04-08 10:18) [14]


> Сергей М. ©   (08.04.08 10:13) [13]


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


 
DelphiN!   (2008-04-08 10:24) [15]


> Сергей М. ©   (08.04.08 10:06) [9]


>
> > процедура SendStream
>
> Чем штатный метод SendStream не угодил ?


Стандартный SendStream отсылает большие объем данных по полностью


 
Сергей М. ©   (2008-04-08 10:25) [16]


> DelphiN!   (08.04.08 10:18) [14]



> Стандартный SendStream отсылает большие объем данных по
> полностью


??


 
DelphiN!   (2008-04-08 10:32) [17]

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

p.Stream.Position:=0;
repeat
 i:=Stream.Read(buff,SizeOf(buff));
 while Socket.SendBuf(buff,i)=-1 do
   until i=0;


WEB страница отображается на клиенте в полном объёме, независимо от размера


 
Сергей М. ©   (2008-04-08 10:35) [18]


> Почему не знаю


Потому что ты закрываешь соединение раньше чем поток передан полностью.

А каким боком тут FB и IBX ?


 
han_malign ©   (2008-04-08 10:52) [19]


> SendStreamParam.Stream := Stream;

SendStreamParam.Stream:= TMemoryStream.Create;
SendStreamParam.Stream.LoadFromStream(Stream);
- время жизни исходного потока какое?


 
DelphiN!   (2008-04-08 11:46) [20]


> Сергей М. ©   (08.04.08 10:35) [18]
>
>
> Потому что ты закрываешь соединение раньше чем поток передан
> полностью.
>


А как закрыть соединение вовремя, если процедура SendStream вызывается несколько раз из события ServerSocketClientRead, ведь мне нужно когда-то закрыть сокет, а когда процедура вызовется последний раз я не знаю и соответственно когда закрыть сокет тоже незнаю


> А каким боком тут FB и IBX ?


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


> han_malign ©   (08.04.08 10:52) [19]
>
>
> > SendStreamParam.Stream := Stream;
>
> SendStreamParam.Stream:= TMemoryStream.Create;
> SendStreamParam.Stream.LoadFromStream(Stream);
> - время жизни исходного потока какое?


Со Stream-ом понятно, спасибо, но когда закрывать сокет?
Исходный Stream живёт недолго. Основной поток(Thread) живёт всегда


 
Сергей М. ©   (2008-04-08 11:51) [21]


> А как закрыть соединение вовремя


Соединение следует закрывать не раньше чем будет вызван деструктор объекта-стрима, переданного параметром в метод SendStream


 
DelphiN!   (2008-04-08 11:59) [22]


> Сергей М. ©   (08.04.08 11:51) [21]


Наверное я плохо объяснил ...


procedure TMain.ServerSocketClientRead(Sender: TObject;
 Socket: TCustomWinSocket);
var
 ...
 Stream: TStream;
begin
 ...
 Stream.LoadFromFile("C:\1.htm");
 SendStream(Socket,Stream); //SendStream отсылает данные и закрывает сокет
 ...
 Stream.LoadFromFile("C:\2.htm");
 SendStream(Socket,Stream); //SendStream пытается отослать данные, но сокет то уже закрыт!

 Socket.Close; //Если закрывать сокет тут, то дочерний поток по отправке данных не успеет отослать все данные
end;

Так где закрывать сокет?


 
Сергей М. ©   (2008-04-08 12:05) [23]

Я вообще-то о штатном методе SendStream веду речь...


 
DelphiN!   (2008-04-08 12:13) [24]


> Сергей М. ©   (08.04.08 12:05) [23]
Я вообще-то о штатном методе SendStream веду речь...


Допустим моя процедура SendStream выглядит так, и использует штатный SendStream


//Отправка данных в отдельном потоке
procedure SendS(Par: Pointer);
var
 i: integer;
 buff: array[0..65536] of byte;
 p: ^TSendStreamParam;
 Socket: TCustomWinSocket;
begin
 try
   SendStreamCriticalSection.Enter;
   try
     if not p.Socket.Connected then
       Exit;
     p.Socket.SendStream(Stream);
   except
     //
   end;
 finally
   SendStreamCriticalSection.Leave;
 end;
end;

//Моя процедура SendStream
function TDATA.SendStream(Socket: TCustomWinSocket; Stream: TStream): Boolean;
var
 c: Cardinal;

 i: Integer;
 buff: array[0..1024] of byte;
begin
 SendStreamParam.Socket := Socket;
 SendStreamParam.Stream := TMemoryStream.Create;
 SendStreamParam.Stream.LoadFromStream(Stream);
 BeginThread(nil,100000,@SendS,@SendStreamParam,0,c);
end;



> Соединение следует закрывать не раньше чем будет вызван
> деструктор объекта-стрима, переданного параметром в метод
> SendStream


Так из OnClientRead процедура DATA.SendStream может вызываться несколько раз, и после каждого вызова она будет закрывать сокет? Тогда как второй вызов DATA.SendStream отошлет данные через закрытый сокет?


 
Сергей М. ©   (2008-04-08 12:22) [25]


> DelphiN!   (08.04.08 12:13) [24]


Какая-то каша у тебя в голове)

Излагай свой прикладной протокол инф.обмена - кто кому что передадает, в какой момент и при каких условиях.

Без его четкого понимания разговор на тему "когда закрывать соединение" лишен всякого смысла.


 
DelphiN!   (2008-04-08 12:40) [26]


> Сергей М. ©   (08.04.08 12:22) [25]


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


procedure TMain.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
...
Stream: TStream;
begin
...
Stream.LoadFromFile("C:\1.htm");
DATA.SendStream(Socket,Stream);
...
Stream.LoadFromFile("C:\2.htm");
DATA.SendStream(Socket,Stream);  

Socket.Close; Однако данные не успевают передаться клиенту, прежде чем произойдёт закрытие сокета в основном потоке
end;

procedure SendS(Par: Pointer);
var
 i: integer;
 buff: array[0..65536] of byte;
 p: ^TSendStreamParam;
 Socket: TCustomWinSocket;
begin
 try
   SendStreamCriticalSection.Enter;
   try
     p := Par;
     if not p.Socket.Connected then
       Exit;
     p.Stream.Position:=0;
     repeat
       i:=p.Stream.Read(buff,SizeOf(buff));
       while p.Socket.SendBuf(buff,i)=-1 do
     until (i=0)or(not p.Socket.Connected);
     p.Stream.Free;
   except
     //
   end;
 finally
   SendStreamCriticalSection.Leave;
 end;
end;

function TDATA.SendStream(Socket: TCustomWinSocket; Stream: TStream): Boolean;
var
 c: Cardinal;
begin
 SendStreamParam.Socket := Socket;
 SendStreamParam.Stream := TMemoryStream.Create;
 SendStreamParam.Stream.LoadFromStream(Stream);
 BeginThread(nil,100000,@SendS,@SendStreamParam,0,c);
end;


Как мне передать данные в браузер полностью, используя не блокирующий режим TServerSocket-a? При этом в отдельный поток нужно брать только отсылку данных. Обработка запроса и формирование отсылаемой информации должны проходить в основном потоке


 
Сергей М. ©   (2008-04-08 12:57) [27]


> в отдельный поток нужно брать только отсылку данных. Обработка
> запроса и формирование отсылаемой информации должны проходить
> в основном потоке


И эта блажь оправдана только тем, что тебе по каким-то причинам не удалось выполнить и то и другое в доп.потоке ?

Мда ..

Ну что ж, хозяин - барин)

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

Только вот юзеров твоего суперпупер-сервера жалко)


 
Сергей М. ©   (2008-04-08 13:09) [28]

Да и вообще - в таких вот условиях соответствующий велосипед уже изобретен: сервер работая в stThreaedBlockung в доп.потоке читает клиентствий запрос, синхронизирует его выполнение и формирование стрима-рез-та с осн.потоком (метод Synchronize), вызывает метод SendStream для возврату клиенту рез-та и преспокойно закрывает соединение.



Страницы: 1 вся ветка

Текущий архив: 2008.05.04;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.018 c
15-1205919660
Empleado
2008-03-19 12:41
2008.05.04
Три закона А. Кларка


2-1207563530
_ozzy_
2008-04-07 14:18
2008.05.04
Как активизировать окно моего приложения?


3-1196670098
Натуля
2007-12-03 11:21
2008.05.04
SQL Server - ADO Connection - Delphi


3-1196411574
keymaster
2007-11-30 11:32
2008.05.04
Delphi+Oracle. Проблема с table of...


2-1207383847
andreil
2008-04-05 12:24
2008.05.04
Преобразовать массив пикселей в BitMap?