Форум: "Сети";
Текущий архив: 2004.07.04;
Скачать: [xml.tar.bz2];
ВнизВторичный поток, деструктор, TClientSocket Найти похожие ветки
← →
Анонимщик © (2004-05-06 15:58) [0]Будьте любезны, помогите разобраться.
Из главного окна создаю вторичный поток, который содержит TClientSocket, пытаюсь этот TClientSocket открыть (безуспешно). Через какое-то время пытаюсь уничтожить поток. Он якобы уничтожается, но, если деактивировать программу, появляется сообщение об ошибке Access violation at adress 0000. А потом программа слетает, а дебаггер говорит: "Project ... raised exception class EOSError with message "System Error. Code: 1400. Недопустимый дескриптор окна"".
С чем связано и как бороься?
Вот код:
Главное окно:
var
SCThread: TSocketCrashThread = nil;
procedure TForm1.Button1Click(Sender: TObject);
begin
if SCThread <> nil then
begin
SCThread.Terminate;
while not PostThreadMessage(SCThread.ThreadID, WM_USER, 0, 0) do Sleep(0);
end else
begin
SCThread := TSocketCrashThread.Create("127.0.0.1", 3000);
SCThread.Resume;
end;
end;
поток:
unit CrashTread;
interface
uses
Classes, ScktComp, Windows;
type
TSocketCrashThread = class(TThread)
private
{ Private declarations }
FClientSocket: TClientSocket;
protected
procedure Execute; override;
procedure SocketClientError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
public
constructor Create(AHost: String; APort: Integer);
destructor Destroy; override;
end;
implementation
{ TSocketCrashThread }
constructor TSocketCrashThread.Create(AHost: String; APort: Integer);
begin
inherited Create(true);
FreeOnTerminate := true;
FClientSocket := TClientSocket.Create(nil);
FClientSocket.Host := AHost;
FClientSocket.Port := APort;
FClientSocket.ClientType := ctNonBlocking;
FClientSocket.OnError := SocketClientError;
FClientSocket.Open;
end;
procedure TSocketCrashThread.SocketClientError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
ErrorCode := 0;
FClientSocket.Close;
end;
destructor TSocketCrashThread.Destroy;
begin
FClientSocket.Free;
inherited;
end;
procedure TSocketCrashThread.Execute;
var
Msg: TMsg;
begin
while GetMessage(Msg, 0, 0, 0) do
begin
DispatchMessage(Msg);
if Terminated then break;
end;
end;
end.
← →
Polevi © (2004-05-06 16:22) [1]clientsocket ты создаешь в основном потоке, а цикл выборки собщений - в дополнителном
смысл ?
← →
Анонимщик © (2004-05-06 16:26) [2]Не, clientsocket - в дополнительном потоке, в коде же написано.
← →
Digitman © (2004-05-06 16:27) [3]
> Анонимщик © (06.05.04 15:58)
создавать объект TClientSocket ты, в принципе, волен в каком угодно потоке
но вот вызов его метода Open() ты должен в том потоке, который предусматривает организацию последующего цикла выборки/диспетч-ции сообщений
← →
Digitman © (2004-05-06 16:30) [4]
> в коде же написано
где ?!
обработчик нажатия кнопули в каком потоке вызывается ? в основном !
значит, конструктор объекта-гнезда выполняется тоже в основном .. и Open() - там же !!
← →
Анонимщик © (2004-05-06 16:38) [5]Так, все, спасибо. Не могу больше позорится.
← →
Verg © (2004-05-06 16:49) [6]Я думаю, что главное - это чтобы Поток(активизации) == Поток(освобождения). Тогда хоть AV не будет.
Ну, а в приведенном примере вообще цикл обработки сообщений в доп. потоке. нужен по-сути лишь для того, чтобы обнаружить флаг Terminated, т.к. обработкой оконных сообщений, предназначенных для FClientSocket будет заниматься главный поток, т.е. тот, который вызвал FClientSocket.Open, который в свою очередь организовал то невидимое окно, на очередь сообщений которого у будуть "сыпаться" события FClientSocket.
← →
Digitman © (2004-05-06 16:55) [7]
> Verg © (06.05.04 16:49) [6]
> обработкой оконных сообщений, предназначенных для FClientSocket
> будет заниматься главный поток, т.е. тот, который вызвал
> FClientSocket.Open
прекрасно же понимаешь, что чуть ли не весь смысл доп.потока при этом теряется ...
← →
Verg © (2004-05-06 17:08) [8]
> Digitman © (06.05.04 16:55) [7]
Вообще так: можешь назвать хоть одно преимущество использования сокетов в асинхронном режиме в доп. потоках?
← →
Digitman © (2004-05-06 17:26) [9]
> Verg © (06.05.04 17:08) [8]
могу.
если поток выполняет не только транспортные ф-ции, а и некие иные, то почему бы нет ?
← →
Polevi © (2004-05-06 18:30) [10]>Verg © (06.05.04 17:08) [8]
просто удобно
да и в случае WSAEventSelect без доп потоков никак, из-за ограничения колва ожидаемых хендлов
← →
Verg © (2004-05-06 20:08) [11]
> Polevi © (06.05.04 18:30) [10]
WSAEventSelect - это отдельный случай, я не про него говорил.
Удобно - это понятия субъективное. Я не вижу ничего удобного. Спец-окно, цикл обработки сообщений, которые посылает этому окну еще один служебный системный поток (по-моему даже не один). Какое-то нелепое построение получается. Столько промежуточных, лишних звеньев!
← →
Digitman © (2004-05-07 08:12) [12]
> Verg © (06.05.04 20:08) [11]
> Спец-окно
это, м.б., и лишнее, но зато ощутимо упрощает использование асинхр.режима : просто установили ctNonBlocking, назначили обработчики - и всех делов ..
> цикл обработки сообщений
а как без него обойтись, если кроме ожидания трансп.событий (WSAEventSelect) или трансп.сообщений спец-окну (WSAAsyncselect) поток в момент ожидания должен иметь способность немедленно реагировать на иные спецсообщения (не относящиеся непосредственно к транспорту), посылаемые ему ?
аргумент в пользу неблок.режима с мультиплексированием плох уже потому, что в моменты тайм-аутов ожидания/опроса поток "мертв" и не может реагировать ни на что иное .. кр.того это усложняет алгоритм, если поток выполняет более чем только трансп.ф-ции
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2004.07.04;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.06 c