Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 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.62 MB
Время: 0.045 c
3-55991
zks
2002-09-23 12:52
2002.10.17
ADO + MSSQL + D6


3-56009
Sergey-ZZZ
2002-09-24 14:16
2002.10.17
MSSQL2000


1-56200
cfk
2002-10-07 14:04
2002.10.17
Передача переменных из DLL и обратно


3-56010
Mark_mark
2002-09-26 14:45
2002.10.17
Oracle Client


1-56194
Ryser
2002-10-07 16:41
2002.10.17
Приостановка выполнения цикла.





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский