Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
2-1207562627
Alex_C
2008-04-07 14:03
2008.05.04
Данные двух TMemoryStream - в один сложить


15-1205998774
Loginov Dmitry
2008-03-20 10:39
2008.05.04
Глючит DeleteFile в WinXP


15-1205908112
Slider007
2008-03-19 09:28
2008.05.04
С днем рождения ! 19 марта 2008 среда


2-1207649935
Семен Кевларвестов
2008-04-08 14:18
2008.05.04
Чем можно скрыть окно ToolTip?


15-1206408609
DimonS
2008-03-25 04:30
2008.05.04
Как заинсталлить драйвер Access?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский