![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вторичный поток, деструктор, TClientSocket
Анонимщик © (2004-05-06 15:58:00)Будьте любезны, помогите разобраться.
Из главного окна создаю вторичный поток, который содержит 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.
Digitman (2004-05-07 08:12:00) [1]
> Verg © (06.05.04 20:08) [11]
> Спец-окно
это, м.б., и лишнее, но зато ощутимо упрощает использование асинхр.режима : просто установили ctNonBlocking, назначили обработчики - и всех делов ..
> цикл обработки сообщений
а как без него обойтись, если кроме ожидания трансп.событий (WSAEventSelect) или трансп.сообщений спец-окну (WSAAsyncselect) поток в момент ожидания должен иметь способность немедленнореагировать на иные спецсообщения (не относящиеся непосредственно к транспорту), посылаемые ему ?
аргумент в пользу неблок.режима с мультиплексированием плох уже потому, что в моменты тайм-аутов ожидания/опроса поток "мертв" и не может реагировать ни на что иное .. кр.того это усложняет алгоритм, если поток выполняет более чем только трансп.ф-ции
Verg (2004-05-06 20:08:00) [2]
> Polevi © (06.05.04 18:30) [10]
WSAEventSelect - это отдельный случай, я не про него говорил.
Удобно - это понятия субъективное. Я не вижу ничего удобного. Спец-окно, цикл обработки сообщений, которые посылает этому окну еще один служебный системный поток (по-моему даже не один). Какое-то нелепое построение получается. Столько промежуточных, лишних звеньев!
Polevi (2004-05-06 18:30:00) [3]>Verg © (06.05.04 17:08) [8]
просто удобно
да и в случае WSAEventSelect без доп потоков никак, из-за ограничения колва ожидаемых хендлов
Digitman (2004-05-06 17:26:00) [4]
> Verg © (06.05.04 17:08) [8]
могу.
если поток выполняет не только транспортные ф-ции, а и некие иные, то почему бы нет ?
Verg (2004-05-06 17:08:00) [5]
> Digitman © (06.05.04 16:55) [7]
Вообще так: можешь назвать хоть одно преимущество использования сокетов в асинхронном режиме в доп. потоках?
Digitman (2004-05-06 16:55:00) [6]
> Verg © (06.05.04 16:49) [6]
> обработкой оконных сообщений, предназначенных для FClientSocket
> будет заниматься главный поток, т.е. тот, который вызвал
> FClientSocket.Open
прекрасно же понимаешь, что чуть ли не весь смысл доп.потока при этом теряется ...
Verg (2004-05-06 16:49:00) [7]Я думаю, что главное - это чтобы Поток(активизации) == Поток(освобождения). Тогда хоть AV не будет.
Ну, а в приведенном примере вообще цикл обработки сообщений в доп. потоке. нужен по-сути лишь для того, чтобы обнаружить флаг Terminated, т.к. обработкой оконных сообщений, предназначенных для FClientSocket будет заниматься главный поток, т.е. тот, который вызвал FClientSocket.Open, который в свою очередь организовал то невидимое окно, на очередь сообщений которого у будуть "сыпаться" события FClientSocket.
Анонимщик (2004-05-06 16:38:00) [8]Так, все, спасибо. Не могу больше позорится.
Digitman (2004-05-06 16:30:00) [9]
> в коде же написано
где ?!
обработчик нажатия кнопули в каком потоке вызывается ? в основном !
значит, конструктор объекта-гнезда выполняется тоже в основном .. и Open() - там же !!
Digitman (2004-05-06 16:27:00) [10]
> Анонимщик © (06.05.04 15:58)
создавать объект TClientSocket ты, в принципе, волен в каком угодно потоке
но вот вызов его метода Open() ты должен в том потоке, который предусматривает организацию последующего цикла выборки/диспетч-ции сообщений
Анонимщик (2004-05-06 16:26:00) [11]Не, clientsocket - в дополнительном потоке, в коде же написано.
Polevi (2004-05-06 16:22:00) [12]clientsocket ты создаешь в основном потоке, а цикл выборки собщений - в дополнителном
смысл ?