Форум: "Начинающим";
Текущий архив: 2008.05.04;
Скачать: [xml.tar.bz2];
ВнизОшибка 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;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.006 c