Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.17.150.163] |
|
Сообщ.
#1
,
|
|
|
Здравствуйте. Есть код который отправляет файл на сервер по частям, а сервер его собирает все работает как надо. Но если этот код засунуть в поток то он отправляет не весь файл, подозреваю что поток посылает данные быстрее чем сервер их может обработать. Есть ли мысль по этому поводу или как организовать синхронизацию с классом.
var FS:TFileStream; MS:TMemoryStream; Buffer:TBytes; GUID:string; CountSection:int64; FullBufferSize:int64; BufferSize:int64; I:Integer; begin try fs:=TFileStream.Create('1.txt',fmOpenRead); FullBufferSize := FS.Size; CountSection := (FullBufferSize div GeneralForm.ClientSettings.max_buffer_size)+1; GUID := Client.ClientModule.ServerMethodsClient.AddNewFileTransfer(FullBufferSize);//<-Создаем кэш на сервере MS := TMemoryStream.Create; BufferSize := GeneralForm.ClientSettings.max_buffer_size;//<-максимальные размер буфера for I := 0 to CountSection do begin if FullBufferSize<=0 then Break; if FullBufferSize<BufferSize then BufferSize := FullBufferSize; Buffer := nil; SetLength(Buffer, BufferSize); FS.ReadBuffer(Buffer, BufferSize); MS.Clear; MS.WriteBuffer(Buffer, BufferSize); MS.Position := 0; Client.ClientModule.ServerMethodsClient.WriteFileOnServer(MS,GUID,BufferSize);//<-отправка буфера FullBufferSize:=FullBufferSize - GeneralForm.ClientSettings.max_buffer_size; end; client.ClientModule.ServerMethodsClient.SetEndFile(GUID);//говорим серверу что файл закончен MS.Destroy; FS.Destroy; |
Сообщ.
#2
,
|
|
|
может через ProcessMessages сделать и не парица?
|
Сообщ.
#3
,
|
|
|
Разобрался, гиглвый файл уходит.
переменные выводим в основной поток constructor TMYT.Create(id: integer); begin inherited create(true); FreeOnTerminate := true; indexF:=id; WriteBlock := 0; lastEndPosition:=0; WriteBlockIn:=1; Sleep(50); GeneralForm.ClientSettings.max_buffer_size := 65000; fs:=TFileStream.Create('1.txt',fmOpenRead); FullBufferSize := FS.Size; CountSection := (FullBufferSize div GeneralForm.ClientSettings.max_buffer_size)+1; GUID := Client.ClientModule.ServerMethodsClient.AddNewFileTransfer(FullBufferSize); EventsForm.EventItem[indexF].ProgressBar.Max := CountSection; MS := TMemoryStream.Create; BufferSize := GeneralForm.ClientSettings.max_buffer_size; BB := 0; Resume; end; procedure TMYT.DoWork; label m1; begin try if (FullBufferSize<=0) then exit; m1: EventsForm.EventItem[indexF].ProgressPosition := BB; if FullBufferSize<BufferSize then BufferSize := FullBufferSize; Buffer := nil; SetLength(Buffer, BufferSize); FS.Position := lastEndPosition; FS.ReadBuffer(Buffer, BufferSize); MS.Clear; MS.WriteBuffer(Buffer, BufferSize); MS.Position := 0; if Client.ClientModule.ServerMethodsClient.WriteFileOnServer(MS,GUID,BufferSize) then lastEndPosition := FS.Position else goto m1; FullBufferSize:=FullBufferSize - GeneralForm.ClientSettings.max_buffer_size; inc(BB); if (FullBufferSize<=0) then begin client.ClientModule.ServerMethodsClient.SetEndFile(GUID); Terminate; MS.Free; FS.Free; end; except end; end; procedure TMYT.Execute; begin inherited; while not Terminated do begin Sleep(10); Synchronize(DoWork); end; end; Если будут какие нибудь замечания выслушаю. |
Сообщ.
#4
,
|
|
|
Цитата PIKACHU @ Если будут какие нибудь замечания выслушаю. Главное замечание: это однопоточный код (гляньте справку на Synchronize и за счёт чего это дело работает). |
Сообщ.
#5
,
|
|
|
А смысл тут делать несколько потоков?
|
Сообщ.
#6
,
|
|
|
Однопоточный в том смысле, что в один момент времени работает только ОДИН поток. Даже если в машине десятиядерник из новых экстремальных серий от Intel. Поэтому комбинация TThread + Synchronize однозначно вызывает тот самый вопрос: А смысл тут делать несколько потоков?
|
Сообщ.
#7
,
|
|
|
Да я в курсе что при Synchronize основной поток не доступен, с потоками не очень силен может что то посоветуете. Писал 2 потока первый получает данные второй записывает и все равно без Synchronize не обошлось данные приходят не все, хотя по Ф8 все приходит.
|
Сообщ.
#8
,
|
|
|
Для начала - убрать всю работу с отображением прогресса (это плюшки, их можно сделать позже, через PostMessage).
Затем: всю логику по созданию объектов данных (типа TMemoryStream и т.п.) убрать из конструктора в метод Execute, т.к. Create работает в контексте потока-создателя (обычно - визуальный поток), а вот сам Execute - это именно новый поток. Далее: что значит "данные приходят не все". Не хватает хвоста данных? Или в середине есть битые куски? |
Сообщ.
#9
,
|
|
|
хвоста не хватает, причем всегда по разному. Есть мысль создать поток в нем и проводить все операции с данными, а в нем уже создать поток который будет передавать стримы, еще была идея внутри потока организовать экземпляр класса client соединятся с сервером и отправлять стримы. Как лучше.
|
Сообщ.
#10
,
|
|
|
Скорее всего, кто-то схлопывает коннект раньше времени (главный поток?), поэтому и получается, что по F8 всё ОК, а при работе обычный путём - хвост недопосылается.
|
Сообщ.
#11
,
|
|
|
В том то и дело что конект не закрывается, так как если начать ещё раз отправлять то опять же уходит часть без хвоста и всегда по разному в одной сессии
|