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

Вниз

Подвисание приложения во время передачи файла...   Найти похожие ветки 

 
SeNtiMeL   (2003-02-03 03:06) [0]

Когда начинаешь передавать файл через Socket.SendStream то подвисает окно программы на время передачи. Как этого избежать.
То же самое происходит и при получениии файла клиентом.
В программах типа IRC отправка файла происходит просто здорово без зависаний и т.п....
Как сделать без зависаний ?


 
ole ©   (2003-02-03 05:39) [1]

Отправляй в отдельном Thread"е


 
Digitman ©   (2003-02-03 11:26) [2]

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

см. событие OnWrite()


 
SeNtiMeL   (2003-02-03 17:38) [3]

а если не сложно приведите пример...


 
ole ©   (2003-02-04 04:55) [4]

Создай Thread: (очень просто)
В методе Execute организуй отправку.
Передать данные потоку, я думаю, не проблема


> см. событие OnWrite()

Если по совету Дижитмэна, то, скорей всего, SendStream не прокатит. Там придется посылать поблочно, ожидая события OnWrite, которое скажет тебе, что очередь передачи свободна и ты можешь кинуть новую порцию данных.


 
Digitman ©   (2003-02-04 08:17) [5]


> ole



> скорей всего, SendStream не прокатит


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


 
ole ©   (2003-02-04 12:20) [6]


> и тут же вновь вызвать этот же SendStream()

Тогда непонятен смысл твоего предложения. У него все виснет и так, а ты предлагаешь что б вообще все повисло.
Как я понимаю, пока не отправится весь блок данных через SendStream, буфер передачи будет постоянно занят (полон).
Другое дело, если отправлять буфера, то всегда можно увидеть через OnWrite, что следует отправить еще один и тд и тп.
И еще, SendStream освободит хэндл, данный ему для передачи данных, что же ты предлагаешь ему отправлять???


 
Digitman ©   (2003-02-04 13:43) [7]


> ole



> У него все виснет и так, а ты предлагаешь что б вообще все
> повисло.


Не говори ерунды. Ничего не повиснет. Заполнение 8к-буфера происходит мгновенно. После этого send-метод в любом случае вернет управление, даже если требуется к передаче в сотни и тысячи раз больше данных.


> Как я понимаю, пока не отправится весь блок данных через
> SendStream, буфер передачи будет постоянно занят (полон).
> Другое дело, если


Неверно понимаешь. Смотри реализацию SendStreamPiece, прежде чем рассуждать и делать выводы.


> Другое дело, если отправлять буфера, то всегда можно увидеть
> через OnWrite, что следует отправить еще один и тд и тп.


Чем тебе TMemoryStream не буфер ? Передал его в метод SendStream(), получил назад управление, проанализировал результат.

Читаем хэлп :

The value returned by SendStream indicates whether any information was successfully written to the connection.

Что, трудно так понять ? True - весь поток передан. False - частично. Если частично, то это означает, что stream-объект еще не разрушен и можно обратиться к любым его св-вам (например, Write для записи в поток доп.данных), в т.ч. св-ву Position (покажет, сколько реально данных на этот момент "вытолкнуто" через буфер передачи в канал)

И, если частично, то не следует "пыжиться", пытаясь следом же вызвать снова SendStream для передачи оставшегося фрагмента потока. Следует дождаться OnWrite и тогда уж вызывать SendStream для ТОГО ЖЕ объекта stream С ТЕМ ЖЕ его св-вом Position, чтобы SendStreamPiece продолжил чтение очер.порции потока в буфер передачи С ТОГО ЖЕ места, с которого предыдущая попытка оказалась неуспешной.


 
Digitman ©   (2003-02-04 13:50) [8]

Вот фрагменты кода, работающего с использованием SendStream в неблок.режиме



TOutgoingMemStream = class(TMemoryStream)
private
FOnDestroy: TNotifyEvent;
public
constructor Create(OnDestroy: TNotifyEvent);
destructor Destroy; override;
end;
...


constructor TOutgoingMemStream.Create(OnDestroy: TNotifyEvent);
begin
inherited Create;
FOnDestroy := OnDestroy;
end;

destructor TOutgoingMemStream.Destroy;
begin
if Assigned(FOnDestroy) then
FOnDestroy(Self);
inherited Destroy;
end;

...

procedure TSocketTransport.DoOnOutgoingStreamDestroyed(Sender: TObject);
begin
FOutgoingStream := nil;
end;

// DataBlock sender
function TSocketTransport.Send(const Data: IDataBlock): Integer;
var
StreamToSend: TMemoryStream;
StreamSize: DWord;
CurPos: DWord;
WaitEvent: THandle;
begin
Result := 0;
if Assigned(Data) then
begin
if ((Data.Signature and CallSig) = CallSig) and (Data.Context = 0) then
begin
WaitEvent := CreateEvent(nil, False, False, nil);
Win32Check(WaitEvent <> 0);
Data.Context := WaitEvent;
end;
Result := Data.Context;
InterceptOutgoing(Data);
StreamToSend := TMemoryStream(Data.Stream);
StreamSize := StreamToSend.Size;
LockOutStream;
try
if not Assigned(FOutgoingStream) then
FOutgoingStream := TOutgoingMemStream.Create(DoOnOutgoingStreamDestroyed);
try
CurPos := FOutgoingStream.Position;
FOutgoingStream.Position := FOutgoingStream.Size;
FOutgoingStream.WriteBuffer(StreamToSend.Memory, StreamToSend.Size);
FOutgoingStream.Position := CurPos;
FWinSocket.SendStream(FOutgoingStream);
except
FOutgoingStream.Free;
raise;
end;
finally
UnLockOutStream;
end;
end;
end;


// OnWrite handler

procedure TSocketTransport.WriteEventHandler(Sender: TObject; Socket: TCustomWinSocket);
begin
try
Socket.SendStream(FOutgoingStream);
except
FOutgoingStream.Free;
raise;
end;
end;



 
SeNtiMeL   (2003-02-05 02:43) [9]

Спасибо тебе большое :)


 
ole ©   (2003-02-06 14:00) [10]

ДиджитМэн:
Спасибо. Действительно все просто.
Вот, если б все твои коментарии были такими подробными... :)


 
Digitman ©   (2003-02-06 16:44) [11]


> ole


Конечно, просто)

Вот если бы все программеры взяли бы за полезную привычку, когда что-то непонятно, заглядывать в документацию и исх.тексты)...



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

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

Наверх




Память: 0.5 MB
Время: 0.016 c
3-87882
Al11
2003-03-11 13:37
2003.03.27
Как сделать так,CalcFields считались сразу для всех записей Query


1-88013
АндрейБ
2003-03-13 18:05
2003.03.27
excel


1-87959
maximkus
2003-03-17 21:55
2003.03.27
Как отключить сочетание alt+f4 ???


3-87883
T{}r(l-l
2003-03-11 11:12
2003.03.27
Cursor+MSSQL


3-87830
Andy Eremin
2003-03-07 10:34
2003.03.27
Пустое поле