Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 18.12.2010, 23:08   #1
FanRa3
Пользователь
 
Регистрация: 04.11.2010
Сообщений: 92
По умолчанию Потоки в Delphi

Помогите разобраться с потоками. В гугле ничего нормального не нашёл. Заранее благодарен
FanRa3 вне форума Ответить с цитированием
Старый 19.12.2010, 00:09   #2
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,430
По умолчанию

Гениальное описание проблемы.

Так не пробовал?
http://yandex.by/yandsearch?clid=958...157&ncrnd=6156
http://www.google.by/search?client=o...hannel=suggest

помоему совсем не сложно.


"нормального" - это смотря с какой стороны смотреть.

Понятно нааписано в книгах.
80% информации в интернете опять же из книг. интернет очень большой. Хочешь сказать ты постоянно натыкаешся на те 20% оставшихся?

Или просто лень искать и читать?
Человек_Борща вне форума Ответить с цитированием
Старый 19.12.2010, 00:12   #3
vovk
!=
Участник клуба
 
Аватар для vovk
 
Регистрация: 08.09.2008
Сообщений: 1,751
По умолчанию

а хелп что уже отменили?
Цитата:
Понятие потока более общее, чем понятие файла. Файл - это совокупность байтов, размещенных на диске, а поток может быть связан и с файлом, и с последовательностью данных в памяти, и с ресурсами, и с внешними устройствами, и с сокетом TCP/IP. Впрочем, в рамках данной книги нас будут интересовать только потоки, так или иначе связанные с файлами. Так что только такие классы потоков мы будем рассматривать.

Базовым классом всех потоков в VCL Win32 и VCL .NET является TStream. В нем объявлены основные свойства и методы, позволяющие организовать чтение и запись данных. Но сам класс TStream - абстрактный, и объекты этого класса создавать нельзя. Мы рассмотрим два его дочерних класса - класс TFileStream, созданный специально для работы с файлами, и класс TMemoryStream, который описывает поток в памяти.

Объект класса TFileStream связывается с файлом в момент вызова конструктора. Первым аргументом в него передается строка с именем файла, а вторым аргументом - флаги режима, в котором открывается файл. Например, следующий код создает файл My.dat и открывает его для записи:

var T: TFileStream;
...
T := TFileStream.Create('My.dat', fmCreate);

Если надо открыть существующий файл только для чтения, вторым аргументом в конструктор надо передать флаг fmOpenRead:

T := TFileStream.Create('My.dat', fmOpenRead);


Флаг fmOpenWrite откроет файл для записи. В этом случае можно заменять или дополнять данные, содержащиеся в файле. Флаг fmOpenReadWrite дает доступ и для чтения, и для записи. В этом режиме можно читать, редактировать и дополнять данные, имеющиеся в файле.

Запись данных в поток осуществляется методом Write. Первым аргументом в этот метод передается значение, которое должно быть записано в файл, а вторым - число записываемых байтов. Функция возвращает действительное число записанных байтов, которое может быть меньше заданного.

Такое словесное описание метода справедливо и для VCL Win32, и для VCL .NET. Однако в действительности определение метода в этих двух библиотеках существенно различается. В VCL Win32 в качестве первого аргумента можно задать численное значение, символ, строку, массив любых данных. А в VCL .NET аргументом может быть только численное значение, символ, или массив байтов. Так что если вам надо записать в файл, например, массив действительных чисел, то в VCL Win32 это легко делается одним оператором, а в VCL .NET запись надо осуществлять в цикле по одному элементу, или предварительно преобразовывать массив чисел в массив байтов.

Пусть, например, объявлен динамический массив действительных чисел:

var A: array of Double;

Он заполняется какими-то результатами расчета, после чего его надо занести в файл, с которым соединен поток T. Поток для этого должен быть открыт в режиме fmCreate, или fmOpenWrite, или fmOpenReadWrite.

В приложении VCL Win32 запись производится одним оператором:

T.Write(A, sizeof(Double) * Length(A));

В вызове метода Write второй аргумент задан равным числу байтов, содержащихся в одном элементе типа Double, умноженному на число элементов массива. В результате в файл запишется весь массив A.

В приложении VCL .NET запись производится несколько сложнее:

for i:=0 to High(A) do
T.Write(A[i], sizeof(Double));

В приведенных примерах запись производится, начиная с первой позиции файла. Если файл был пустой (открывался в режиме fmCreate), то файл будет содержать только сделанную запись. Но если в файле уже было нечто записано и он открывался в режиме fmOpenWrite или fmOpenReadWrite, то новая запись будет сделана поверх того, что уже было записано в файле. Если новая запись короче прежней, то после ее окончания в файле останется конечная часть предшествующих записей. В потоке имеется свойство Position - текущая позиция. Именно это свойство определяет позицию, в которую производится запись методом Write. В момент создания потока Position = 0. А после каждого вызова метода Write позиция сдвигается на число записанных байтов. Именно поэтому в приведенном примере для приложения VCL .NET каждый вызов Write записывал очередной элемент после предыдущего.

Свойство Position можно изменять перед записью, управляя таким образом позицией, в которую производится запись. Например, в файле, открытом в режиме fmOpenWrite или fmOpenReadWrite, можно новые данные записывать в конец файла, не уничтожая содержащуюся в файле информацию. Для этого перед операторами вызова Write надо вставить оператор:

T.Position := T.Size;

Этот оператор задает текущую позицию равной Size - свойству потока, содержащему общее число байтов в файле.

Последний раз редактировалось vovk; 19.12.2010 в 00:21.
vovk вне форума Ответить с цитированием
Старый 19.12.2010, 00:23   #4
vovk
!=
Участник клуба
 
Аватар для vovk
 
Регистрация: 08.09.2008
Сообщений: 1,751
По умолчанию

дальше ю
Цитата:
Чтение данных из потока осуществляется методом Read. Поток при этом должен быть создан в режиме fmOpenRead или fmOpenReadWrite. Параметры метода Read не отличаются от рассмотренных ранее для метода Write. Так что чтение файла, в который в предыдущих примерах были записаны данные, в динамический массив A в приложении VCL Win32 производится следующим образом:

SetLength(A, T.Size div sizeof(Double));
T.Read(A, T.Size);

Для определения размера массива использовано свойство Size потока, указывающее число байтов в потоке, т.е. в файле. Частное от деления этого значения на число байтов в типе Double дает количество записанных в файле действительных чисел. А затем все эти числа читаются одним вызовом метода Read.

В приложении VCL .NET чтение может быть оформлено так:

SetLength(A, T.Size div sizeof(Double));
for i:=0 to High(A) do
T.Read(A[i], sizeof(Double));

В приведенных примерах чтение производилось, начиная с первой позиции файла, поскольку, как уже говорилось, в момент создания потока его текущая позиция Position = 0. А после каждого вызова метода Read позиция сдвигается на число прочитанных байтов. Именно поэтому в приведенном примере для приложения VCL .NET каждый вызов Read читал очередной записанный элемент.

Задавая значение свойства Position, вы можете читать не весь файл, а только тот записанный в нем элемент, который вам в данный момент нужен. Таким образом, файл обеспечивает произвольных доступ к записанным данным. Если вы знаете, что в файле записаны только значения типа Double, и вам надо прочитать в некоторую переменную B элемент с порядковым номером I, то это можно сделать операторами:

T.Position := (I - 1) * sizeof(Double);
T.Read(B, sizeof(Double));

Позицию можно изменять не только свойством Position, но и методом Seek. Первый параметр этого метода указывает, на сколько должна быть сдвинута текущая позиция. Положительные значения соответствуют сдвигу к концу, а отрицательные - к началу потока. Второй параметр метода указывает, от какой точки отсчета задается сдвиг первым параметром. Этот параметр может принимать значения soBeginning - сдвиг относительно начала потока, soCurrent - сдвиг относительно текущей позиции, soEnd - сдвиг относительно конца потока (тогда сам сдвиг должен задаваться отрицательным). Так что в предыдущем примере задание позиции можно было бы выполнить не прямым изменением значения Position, а оператором:

T.Seek((I - 1) * sizeof(Double), soBeginning);

Впрочем, если требуемая позиция отсчитывается от начала файла, то вряд ли имеет смысл использовать метод Seek. Проще задать значение Position. Но если, например, требуется прочитать элемент с порядковым номером I, отсчитываемым от конца файла, то, может быть, использование метода Seek проще:

T.Seek(-I * sizeof(Double), soEnd);

Если поток создан в режиме fmOpenReadWrite, то можно осуществлять редактирование записанных в поток данных. Пусть, например, вам надо умножить на 10 число, записанное в файл под порядковым номером I. Это можно сделать следующим образом:

T.Position := (I - 1) * sizeof(Double);
T.Read(B, sizeof(Double));
T.Position := T.Position - sizeof(Double);
T.Write(B * 10, sizeof(Double));

Первый оператор подводит текущую позицию к месту размещения в файле искомого числа. Вызов метода Read читает это число в переменную B. Во время чтения текущая позиция сдвинулась на число байтов, которое занимало прочитанное число. Поэтому третий оператор сдвигает позицию назад к началу прочитанного числа. А последний оператор методом Write записывает число, умноженное на 10.

У потока имеется еще один интересный метод - CopyFrom. Он копирует в данный поток из другого потока, заданного первым параметром, число байтов, заданное вторым параметром. Если второй параметр задан равным 0, то копируется поток целиком. Копирование начинается с текущей позиции потока-источника в текущую позицию потока-приемника.

Этот метод дает простой и эффективный способ копирования любых файлов. Например:

var T1, T2: TFileStream;
...
T1 := TFileStream.Create('f.dat', fmOpenRead);
T2 := TFileStream.Create('f2.dat', fmCreate);
T2.CopyFrom(T1, 0);
FreeAndNil(T1);
FreeAndNil(T2);

Приведенный код копирует файл f.dat в файл f2.dat. Заключительные операторы закрывают потоки T1 и T2.
vovk вне форума Ответить с цитированием
Старый 19.12.2010, 00:24   #5
vovk
!=
Участник клуба
 
Аватар для vovk
 
Регистрация: 08.09.2008
Сообщений: 1,751
По умолчанию

конец .
Цитата:
При незначительном изменении аналогичный код может осуществлять не копирование, а объединение файлов:

var T1, T2: TFileStream;
...
T1 := TFileStream.Create('f.dat', fmOpenRead);
T2 := TFileStream.Create('f2.dat', fmOpenWrite);
T2.Position := T2.Size;
T2.CopyFrom(T1, 0);
FreeAndNil(T1);
FreeAndNil(T2);

В приведенном коде жирным шрифтом выделены отличия от предыдущего примера. Файл f2.dat открывается в режиме fmOpenWrite, так что содержащиеся в нем данные сохраняются. Следующий оператор сдвигает текущую позицию потока T2 в конец файла. В результате копия файла f.dat записывается в конец файла f2.dat.

Теперь рассмотрим особенности использования потоков класса TMemoryStream. Поток этого класса создается в памяти. При своем создании он не связывается ни с каким источником. Если требуется связать поток с файлом, то используется метод потока LoadFromFile, в который передается имя файла. Метод загружает в поток содержимое файла, уничтожая данные, которые находились в потоке до этого. Размер отводимой памяти и соответственно значение свойства Size в точности становится равным размеру файла. После этого можно применять к потоку любые методы записи и чтения, которые были рассмотрены выше для потока TFileStream. Поскольку все операции производятся в памяти, эффективность их высокая. Если данные в потоке изменяются, то сохранить их в дальнейшем в файле можно методом SaveToFile, в который передается имя файла. Если указанный файл не может быть создан или открыт для записи, генерируется исключение EFCreateError.

Таким образом, работа с потоком, связанным с файлом, может быть организована следующим образом:

var T: TMemoryStream;
...
T := TMemoryStream.Create;
T.LoadFromFile('f.dat');
// операторы изменения данных
...
T.SaveToFile('f.dat');
FreeAndNil(T);


Поток TMemoryStream обеспечивает очень простой способ копирования файлов. Достаточно загрузить в поток данные из одного файла и сохранить их в другом файле:

T.LoadFromFile('f.dat');
T.SaveToFile('f2.dat');


Для объединения нескольких файлов можно создать дополнительный поток, загружать в него поочередно различные файлы и присоединять их данные в конец первого потока описанным ранее методом CopyFrom, или методом SaveToStream. Этот метод копирует все данные из потока, созданного в памяти, в другой указанный поток, начиная с его текущей позиции Position.

Ниже приведен пример создания файла f3.dat, объединяющего файлы f.dat, f1.dat и f2.dat.



var T, T1: TMemoryStream;
...
T := TMemoryStream.Create;
T1 := TMemoryStream.Create;
T1.LoadFromFile('f.dat');
T.CopyFrom(T1, 0);
T1.LoadFromFile('f1.dat');
T.CopyFrom(T1, 0);
T1.LoadFromFile('f2.dat');
T.CopyFrom(T1, 0);
...
T.SaveToFile('f3.dat');
FreeAndNil(T);
FreeAndNil(T1);

В этом примере использован метод CopyFrom. В поток T1 поочередно загружаются данные различных файлов. Поскольку метод CopyFrom сдвигает текущую позицию потока T на конец данных, скопированных из потока T1, следующий вызов CopyFrom копирует новые данные в конец потока, т.е. объединяет прежние и новые данные. В заключение методом SaveToFile данные потока T сохраняются в файле f3.dat. Если этот файл ранее не существовал, он создается. Если же он существовал, то его прежнее содержимое стирается и заменяется новым.

Вместо метода CopyFrom в предыдущем примере можно было бы использовать метод SaveToStream. Для этого достаточно заменить все операторы

T.CopyFrom(T1, 0);


операторами

T1.SaveToStream(T);
ЭЭх а фины продули(хоккей)))
vovk вне форума Ответить с цитированием
Старый 19.12.2010, 02:05   #6
FanRa3
Пользователь
 
Регистрация: 04.11.2010
Сообщений: 92
По умолчанию

а можете собрать исходник, в котором показана работа с потоками? так мне легче будет понять, как это работает)
FanRa3 вне форума Ответить с цитированием
Старый 19.12.2010, 02:16   #7
vovk
!=
Участник клуба
 
Аватар для vovk
 
Регистрация: 08.09.2008
Сообщений: 1,751
По умолчанию

тут посмотрите первая же ссылка, поиск по форуму тоже поможет, ну это же общие вопросы, которые уже не 1 десяток раз обсуждались, ничего нового просто скахзать не выйдет, а пересказывать давно уже сказаное ну просто неинтерестно))
vovk вне форума Ответить с цитированием
Старый 19.12.2010, 04:10   #8
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Вы бы для начала сказали, чего вам надо.

Потому что потоки есть потоки данных (stream) и потоки кода (thread, нить). Как несложно догадаться, общего между ними - ноль.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 19.12.2010, 11:30   #9
FanRa3
Пользователь
 
Регистрация: 04.11.2010
Сообщений: 92
По умолчанию

я видел урок, где объяснялось добавление текста в Memo с помощью 2 потоков. Там всё подробно объяснялось, но вот сейчас не могу его найти
FanRa3 вне форума Ответить с цитированием
Старый 19.12.2010, 11:49   #10
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
FanRa3
Речь идет о TThread? О сихронизации потоков?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Потоки в Delphi ChEaTeR-abc Помощь студентам 3 14.07.2010 17:40
Потоки (Delphi) VadEr Помощь студентам 0 11.04.2010 18:24
Delphi потоки и графические линии world12_tk Помощь студентам 0 13.03.2010 16:03
Проблема в Delphi. Возможно, на потоки. Jean-Esther Помощь студентам 2 21.02.2009 22:32
Потоки в Delphi frai Общие вопросы Delphi 4 13.01.2008 03:39