多线程等待窗口的问题 ( 积分: 300 )

  • 主题发起人 主题发起人 Rover
  • 开始时间 开始时间
R

Rover

Unregistered / Unconfirmed
GUEST, unregistred user!
我的程序要使用Socket连接服务器,期间等待时间相对较长,需要一个弹出窗口显示连接过程。我用多线程显示弹出窗口,始终控制不好。
谁有代码给我参考参考。
 
我的程序要使用Socket连接服务器,期间等待时间相对较长,需要一个弹出窗口显示连接过程。我用多线程显示弹出窗口,始终控制不好。
谁有代码给我参考参考。
 
说说我的用法,VCL很多控件都是线程不安全的,所以有个函数同步,原理网上有很多文章,我介绍的方法
首先,不建议你说的所谓那个窗口,而是把进度直接显示在主窗体上,你可以做一个panel,平时隐藏就可以了,要传进度过来肯定需要一些变量,姑且认为只有三个变量吧,一个是进度的文字信息,一个进度的总时间,一个是进度的当前位置,那么我就在线程这个单元里面建立一个结构类型
TProgressInfo = record
nPos, nTotal : Integer;
strText : string;
end;

然后自己定义一个消息
const
WM_PROGRESS = WM_USER + 101;
在线程里面execute里面准备发送进度的时候,你就定义一个变量
比如
var
p : TProgressInfo ;

begin
……
p.nPos := 1;
p.nTotal := 100;
p.strText := '正在连接';
// 向主界面发送消息,p作为LParam来发送
……
end;

在主界面上
procedure GetMessage(var msg : TMessage);message WM_PROGRESS;
相应这个消息取得msg的LParam参数
后面就你自己取了,这样基本上可以达到你的要求
 
感觉楼上的意思是把p的地址传到主窗口,这样有些不妥吧,万一主窗口处理消息时,在线程中的p已经被修改或释放了。这样程序就要出错了吧
 
做了几个项目,都还比较稳定,这种方式不错,至于里面的处理,等高人来指点一下,也可以不传地址,看具体需要
 
也在做,关注这个问题;
连接时间不知道有没有可以限时的.
 
>>我用多线程显示弹出窗口,始终控制不好。
应该用子线程连接服务器,在主线程中显示弹出窗口,这样好控制的多
其实作简单的办法就是用异步i/o(比如用WSAAsyncSelect 注册消息),开始连接时显示窗口提示正在连接,连接成功之后会有消息通知,这时候关闭提示窗口。
 
能给个例子看看吗?
 
chenybin能不能给个具体代码?
谢谢
 
晕,应该把你的socket连接放在另外的一个线程里,而不是把窗口放在其他线程,窗口之类的资源一般都在主线程中执行~~~~~`
 
你把socket连接改成非阻塞的不就行了。。。。。
或者把socket放到线程里
或者。。。这样试试,不保证可用。。。。因为form2也是属于主线程的,你可以把from2在线程里创建
type
TThreadForm = class(TThread)
protected
procedure Execute;
override;
public
end;

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
threadform:TThreadForm;
implementation
uses unit2;
{$R *.dfm}
procedure TThreadForm.Execute;
var
i:integer;
begin
i:=0;
freeonterminate:=true;
form2.Show;
while not terminateddo
begin
//改变窗口显示
sleep(100);
end;
form2.Close;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
threadform:=TThreadForm.Create(false);
//socket请求
threadform.Terminate;
end;
 
历经千辛万苦阿(凌晨哦),下面的代码演示怎么从线程里面发消息到主窗口,其实只是一个地址而已,问题都不大,几个大项目都这样处理的。可以解决。至于怎么连接Socket都放可以在线程里面处理了,希望对你有帮助
Unit2.pas
unit Unit2;
interface
uses
Classes, Messages, windows;
const
WM_Info = WM_USER + 100;
type
TInfo = record
nPos, nTotal: Integer;
end;

TMyThread = class(TThread)
private
{ Private declarations }
FMainHandle : THandle;
nPos : Integer;
nTotal : Integer;
protected
procedure Execute;
override;
public
constructor Create(CreateSuspended: Boolean;
_MainHandle : THandle;
_Total: Integer);reintroduce;
end;

implementation

{ TMyThread }
constructor TMyThread.Create(CreateSuspended: Boolean;
_MainHandle: THandle;
_Total: Integer);
begin
Inherited Create(CreateSuspended);
FMainHandle := _MainHandle;
nPos := 0;
nTotal := _Total;
end;

procedure TMyThread.Execute;
var
p : TInfo;
begin
while not Terminateddo
begin
if nPos < nTotal then
begin
p.nPos := nPos;
p.nTotal := nTotal;
Inc(nPos);
if FMainHandle <> 0 then
SendMessage(FMainHandle, WM_Info, 0, Integer(@P));// 向主窗口发送消息
end;
end;
end;

end.

unit1.pas
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, unit2, StdCtrls, ComCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
ProgressBar1: TProgressBar;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
Thread : TMyThread;
public
{ Public declarations }
procedure Info(var msg : TMessage);
message WM_Info;
constructor Create(AOwner : TComponent);override;
destructor Destroy;
override;
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
constructor TForm1.Create(AOwner: TComponent);
begin
inherited;
Thread := TMyThread.Create(True, Self.Handle, 100000);
end;

destructor TForm1.Destroy;
begin
Thread.Terminate;
inherited;
end;

procedure TForm1.Info(var msg: TMessage);
var
P : TInfo;
begin
if msg.Msg = WM_Info then
begin
// 先判断消息类型
p := TInfo(Pointer(msg.LParam)^);// 取出对应地址里面的东西
ProgressBar1.Max := p.nTotal;// 更新界面
ProgressBar1.Min := 0;
ProgressBar1.Position := p.nPos;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if Thread.Suspended then
Thread.Resume
else
Thread.Suspend;
end;

end.
 
比较简单的方法就是在线程中直接操纵显示进度的窗体,记得同步就行了。
 
我有一个与楼主类似的问题,在多线程中,有一个窗口与用户交互,等待用户输入后才继续执行剩余部分,线程的EXECUTE方法大概是这样:
线程的前半部分...
调用交互窗口,等待用户输入
线程的后半部分...
现在的问题是:
这个窗口不能用MODAL的方式来显示(原因我想你该知道),但以SHOW的方式显示出来后,线程不会等待用户输入,就接着执行后半部分了.
请教有什么好办法可以处理,告诉一下思路就好.
 
后退
顶部