Форум: "Сети";
Текущий архив: 2002.10.17;
Скачать: [xml.tar.bz2];
ВнизВот такая проблемма! Найти похожие ветки
← →
Le! (2002-07-31 08:20) [0]Народ помогите. Такая проблемма: есть два сокетных соединения, нужно чтобы они работали одновременно. у меня получается, что они работают по очереди. как быть подскажите!
← →
Digitman (2002-07-31 12:27) [1]Организовать каждое сокетное соединение в доп. кодовом потоке.
← →
Le! (2002-08-01 07:52) [2]Всмысле? это как?
Вот я беру компонент Powersock( две шкуки) помещаю на форму и дальше говорю им куда коннектица, вот и они у меня работают поочередно, т.е. пока один не сконектица второй и не приступит. вот.
← →
Digitman (2002-08-01 08:12) [3]см. класс TThread
← →
Le! (2002-08-10 08:19) [4]Ну вот нашел такой пример:
Пример 2. "Поединок" Thread-ов :-).
{В форму Form1 нужно поместить TCheckBox - CheckBox1
и одну кнопку TButton - Button1}
{Определение классов двух Thread-ов}
type
TMyThread1 = class(TThread)
private
{ Private declarations }
protected
procedure DoWork;
procedure Execute; override;
end;
TMyThread2 = class(TThread)
private
{ Private declarations }
protected
procedure DoWork;
procedure Execute; override;
end;
var Form1: TForm1;
T1 : TMyThread1;
T2 : TMyThread2;
implementation
procedure TMyThread1.Execute;
begin
{Пока процесс не прервали, выполняем DoWork}
while not Terminated do
Synchronize(DoWork);
end;
procedure TMyThread2.Execute;
begin
{Пока процесс не прервали, выполняем DoWork}
while not Terminated do
Synchronize(DoWork);
end;
procedure TMyThread1.DoWork;
begin
{Пытаемся победить второй процесс :-)}
Form1.CheckBox1.Checked := True;
end;
procedure TMyThread2.DoWork;
begin
{Пытаемся победить первый процесс :-)}
Form1.CheckBox1.Checked := False;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
{Если кнопка называется Stop...}
if Button1.Caption = "Stop" then begin
{Прерываем оба процесса}
T1.Terminate;
T2.Terminate;
{Изменяем название кнопки}
Button1.Caption := "Start";
{Выходим из процедуры}
Exit;
end;
{Создаем и сразу запускаем два процесса}
T1 := TMyThread1.Create(False);
T2 := TMyThread2.Create(False);
{Здесь можно поэкспериментировать с приоритетами:
T1.Priority := tpLowest;
T2.Priority := tpHighest;
}
{Переименовываем кнопку}
Button1.Caption := "Stop";
end;
Вместо переключения CheckBox"ов ставлю свой код с Powersock, и всеравно это два тотока выполняются у меня поочередно.
Как быть!
← →
Polevi (2002-08-10 17:51) [5]2Le!
ты нашел очень плохой пример
смотри хелп по Synchronize
← →
Le! (2002-08-13 07:54) [6]а где найти получше?
и тут же используется Synchronize. что с ним не так?
скажу чесно помимо этого я нашел ещё 2 примера использования Thread, но те у меня не пошли и я не смог с ними разобраться.
← →
Digitman (2002-08-13 08:16) [7]>Le!
Не с примера нужно начинать, а с чтения документации до полного понимания сути потоковой организации процессов Win32
← →
Le! (2002-08-14 08:21) [8]Прежде как обратится суда, я все что нашел перечитал.
практически ничего не понел, и решил здесь спросить думал мне здесь помогут.
← →
Digitman (2002-08-14 08:40) [9]Ну так и задавай вопрос не в форме "нужно чтобы .. как быть", а конкретно - "мне непонятно то-то и то-то в таком-то описании того-то или в таком-то примере". С конкретными ссылками/цитатами на непонятные фразы/строчки кода.
Или "думал мне здесь помогут" = "дайте готовый код" ?
← →
Le! (2002-08-15 08:30) [10]Молодец: "думал мне здесь помогут" = "дайте готовый код" - правильный ответ, ставлю 5!
Но правда позновато, я уже сам дошел, и вот что получается:
вообщем делаю такой код:
unit unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, unit2;
type
TForm1 = class(TForm)
Label1: TLabel;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
co:TCountObj;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
co:=TCountObj.Create(true);
co.Resume;
co.Priority:=tpLower;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
co.Terminate;
co.Free;
end;
end.
unit unit2;
interface
uses
Classes, Sysutils;
type
TCountObj = class(TThread)
private
{ Private declarations }
index:Integer;
procedure UpdateLabel;
protected
procedure Execute; override;
end;
implementation
uses unit1;
{ TCountObj }
procedure TCountObj.Execute;
begin
index:=1;
while index>0 do
begin
Synchronize(UpdateLabel);
Inc(index);
if index>100000 then
index:=0;
if terminated then exit;
end;
end;
procedure TCountObj.UpdateLabel;
begin
Form1.Label1.Caption:=IntToStr(Index);
end;
end.
При нажатии кнопки: число на форме начинает бежать.
Интересно что при нажатии ещё раз: ничинается ещё один цикл.
Получается, как я понел два потока, но при нажатии ещё несколько раз получается столько потоков сколько раз мы нажали кнопку. Первый вопрос: почему это так?
Опять интересно, что остановить(нажатием второй кнопки) можно лишь первый цикл, при повторном нажатии кнопки выдает какуюто ошибку.
Второй вопрос: что не так в этом коде?
Подставляя на место цикла свой цикл с Powersock, получаем его нормальную работу, но при нажатии ещё раз, выдает ошибку что Powersock уже сконектен.
Вопрос третий: Можно ли сделать несколько потоков на одном Powersock, или для этого лучше использовать чтото другое?
Для второго Powersock сделал ещё один класс TThread, так работает все нормально. но я пошел дальше сделал ещё 8 классов, в итоге у меня появилось 10 Powersock"ов, которые работают нормально. вот такая история.
Вот тебе конкретные вопросы по конкретному примеру.
← →
Digitman (2002-08-15 10:04) [11]
> Первый вопрос: почему это так?
Потому что всякий раз при нажатии кнопки создается новый, совершенно автономный объект класса TThread, в конструирующем методе которого происходит создание нового кодового потока как ОС-объекта.
> Второй вопрос: что не так в этом коде?
1.
co:=TCountObj.Create(true);
всякий раз при выполнении этой строчки ты теряешь содержимое переменной co, теряя тем самым ссылку на объект, созданный тобой при предыдущем выполнении этой же строчки. Т.е. фактически происходит потеря объекта в памяти, кодовый поток, созданный потерянным объектом, становится попросту неуправляемым, неподконтрольным тебе, поскольку уничтожить "потерянный" поток ты не имеешь возможности : ссылку на управляющий им соответствующий объект класса TCountObj ты уничтожил собственными руками, "затерев" ее ссылкой на другой такой же объект.
Здесь важно понимать, что каждый объект класса TThread создает и контролирует (и всегда ассоциирован с) отдельный ОС-объект-кодовый поток. При уничтожении экземпляра класса TThread вызовом Free происходит неявный вызов метода Terminate, в теле которого взводится флаг Terminated, доступный телу метода Execute (то, что происходит в Execute, собственно и выполняется в контексте соответствующего кодового потока, создаваемого ДАННЫМ экземпляром TThread). Код в теле метода Execute при выполнении длительных вычичлений обязан реагировать на состояние флага Terminated, и, в случае обнаружения условия Terminated = True, прервать вычисления и завершиться (как завершается обычная процедура). Исключения в методе Execute недопустимы, их нужно "гасить", заключая потенциально опасные участки кода в блоки try..execpt.
2.
// если не требуется перед разрушением экземпляра прочитать код возврата потока, следующая строчка необязательна
co.Terminate; // вопрос к тебе : к какому экз-ру TThread обращаешься ? Ты их кучу насоздавал, давя кнопку Button1
//если же строчка выше присутствует, здесь при необходимости можно прочитать код возврата потока
//
co.Free;//тот же вопрос : какой экз-р разрушаешь ? ответ : самый последний созданный; остальные утеряны тобой и недоступны/неподконтрольны
3. Метод Synchronize(UpdateLabel) в данном случае уместен, поскольку синхронизирует выполнение метода UpdateLabel с осн.потоком процесса, что обязательно из-за обращения к визуальному контролу TLabel, не являющемуся (как и все иные визуальные контролы) thread-safe (небезопасным с т.з. обращения ко многим его методам/свойствам из любого иного кодового потока, нежели основной).
В общем же случае метод Synchronize() нужен только для синхронизации с осн.потоком выполнения методов класса TThread, в теле которых происходит обращение к любым non-thread-safe-объектам/ресурсам (TPowersock, помнится, как раз thread-safe).
Синхронизация же как раз и нужна для ПОСЛЕДОВАТЕЛЬНОГО выполнения действий со стороны нескольких кодовых потоков над одними и теми же неразделяемыми ресурсами системы.
> Можно ли сделать несколько потоков на одном Powersock
Вопрос некорректен. Кодовые потоки не "делаются" ни на чем, они начинают свое существование "сами по себе", в результате вызовов ф-ций CreateThread(), инкапсулированных в конструктор класса TThread. Код же метода Execute() может делать все что угодно : создавать/уничтожать/управлять индивидуальными объектами (в т.ч. и класса TPowersock).
Классическая схема в твоем случае будет такова :
1. Декларируешь единственный класс-наследник TCountObj = class(TThread)
2. Либо в переопределенном конструкторе класса либо в теле Execute() создаешь отдельный объект класса TPowersock и инициализируешь его. ссылку на объект фиксируешь в одном из специально определенных полей класса TCountObj.
3. В методе Execute() обращаешься к транспортным методам/св-вам/событиям собственного экз-ра TPowersock , используя ранее сохраненную ссылку на него. В ходе вычислений в Execute() как можно чаще контролируешь флаг Terminated, чтобы как можно оперативней завершить тело Execute() по требованию со стороны кода, создавшего поток.
4. При нормальном/аварийном завершении либо по требованию извне разрушаешь собственный экземпляр TPowersock либо в финальных дествиях метода Execute() либо в деструкторе данного экземпляра TCountObj.
> Для второго Powersock сделал ещё один класс TThread..
Ну, наверно-таки не "еще один класс" , а "еще один экземпляр класса" ? Абсолютно разные вещи !
Зачем создавать еще один класс-наследник TThread, если создаваемый им кодовый поток должен выполнять в точности те же вычисления (иметь точно такое же тело метода Execute) ? Достаточно вызвать еще раз конструктор уже созданного тобой класса - и новый кодовый поток будет создан и будет выполняться параллельно с кодовыми потоками, созданными при предудущих вызовах конструктора того же класс-наследника TThread
← →
Le! (2002-08-16 07:49) [12]Спасибо.
Если что то будет не так, то жди вопросов.
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2002.10.17;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.007 c