+ -
当前位置:首页 → 问答吧 → 多线程中控制子窗体的问题

多线程中控制子窗体的问题

时间:2011-09-09

来源:互联网

是这样的 

主窗体 A中打开了一个子窗体B B窗体中用多线程来下载显示一个图片

A中

Delphi(Pascal) code

  B.Show();
  B.DownLoadShowPicture('图片地址');



B中
Delphi(Pascal) code

  Procedure TFrom2.DownLoadShowPicture(URL:String);
  Begin
    PICURL := URL;
    Thread := createthread(nil,0,@DownLoadShowPictureThread,nil,0,TID)
  End

  Procedure DownLoadShowPictureThread();
  Begin
    // 先载并显示图片的过程

    Form2.Width := 图片宽;
    Form2.Height := 图片高;
    Status.Text := '完成';
  End


  
问题是在 DownLoadShowPictureThread()线程中 无法改变 Form2的尺寸以及Status的Text值(其实值已经改变(通过之后的MessageBox显示出来的是改变后的值 只是窗体上显示的无任何变化..)..

作者: bingo_   发布时间: 2011-09-09

主线程失去响应

作者: jingtuzhong   发布时间: 2011-09-09

Procedure DownLoadShowPictureThread.execute;应该这样写吧

作者: jingtuzhong   发布时间: 2011-09-09

主窗体 A中打开了一个子窗体B B窗体中用多线程来下载显示一个图片

--------------------------------------------------------

这个业务应该是这样描述:主窗体中要调用一个下载图片并显示的功能。创建一个线程并下载了窗体后,在将下载完成的消息传递给窗体B,窗体B在显示图片。
代码写成下面这样子,就更明了了。
----------------------------------
窗体A 的打开代码
Delphi(Pascal) code

procedure TForm1.btn1Click(Sender: TObject);
var
  AFileName:String;
begin
   if CreateWinForm2('要下载的URL',AFileName) then
    Showmessage('下载成功:'+AFileName)
   else
    Showmessage('下载失败!!')
end;



窗体B的代码
Delphi(Pascal) code

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

const
  WM_DownFile=WM_USER+4500;

type
  TDownThread=class(TThread)
  private
    FWinHandle: THandle;
    FURL: String;
    FFileName: String;
  protected
    procedure Execute;override;

  published
    property FileName:String read FFileName;
    property URL:String read FURL write FURL;
    property WinHandle:THandle read FWinHandle write FWinHandle;
  end;

  TForm2 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FURL: String;
    procedure SetURL(const Value: String);
    function GetFileName: String;
    { Private declarations }
  public
    { Public declarations }
    FDownThread:TDownThread;
    procedure OnWM_DownFile(var msg:TMessage);message WM_DownFile; 
  published
    property FileName:String read GetFileName;
    property URL:String read FURL write SetURL;
  end;

  function CreateWinForm2(const URL:string;var FileName:String):Boolean;

implementation

{$R *.dfm}

function CreateWinForm2(const URL:string;var FileName:String):Boolean;
var
  Form2: TForm2;
begin
  Result:=False;
  Form2:=TForm2.Create(Application);
  Form2.URL:=URL;
  Form2.ShowModal;
  Result:=mrOK=Form2.ModalResult;
  if Result then
    FileName:=Form2.FileName;

  Form2.Free;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  FDownThread:=TDownThread.Create(True);
  FDownThread.WinHandle:=Self.Handle;
end;

procedure TForm2.SetURL(const Value: String);
begin
  FURL := Value;
  if Assigned(FDownThread) then
    FDownThread.URL:=Value;
end;

procedure TForm2.FormShow(Sender: TObject);
begin
  FDownThread.Resume;
end;

{ TDownThread }

procedure TDownThread.Execute;
begin
  inherited;
  //下载

  FFileName:='下载保存后的文件名';
//  if 下载成功 then
    PostMessage(WinHandle,WM_DownFile,100,0);
//  else
//    PostMessage(WinHandle,WM_DownFile,0,0);
end;

procedure TForm2.OnWM_DownFile(var msg: TMessage);
begin
  if msg.WParam=100 then  //下载成功
    ModalResult:=mrOk
  else if msg.WParam=0 then // 下载失败
    ModalResult:=mrCancel;
end;

function TForm2.GetFileName: String;
begin
  Result:=FDownThread.FileName;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  FDownThread.Free;
end;

end.

作者: ZyxIp   发布时间: 2011-09-09

最终解决办法就同3楼 下载图片的线程在A窗体中创建然后传递给B窗体~ 其实我想知道为什么在B窗体中创建下载线程后会出现顶楼所述现象(就是无论在这个线程中做什么也无法改变B窗体以及他上面的任何元素)

作者: bingo_   发布时间: 2011-09-09

你的软件启动后,其实是创建了一个主线程的,用来展示界面这些工作。你自己创建的线程如果直接去操作主线程里的元素,很容易造成两个线程冲突,因为操作界面的这些方法都是没有进行线程同步保护的,即不是线程安全的。所以会造成主线程错误,死锁。

楼主在 线程的 DownLoadShowPictureThread 方法中直接去操作属于主线程的数据,就肯定会有问题了.
窗体和所有的控件只不是属于主线程的数据。我觉得很多初学者都没有理解这些问题,觉得窗体是一个独立的东西。

作者: ZyxIp   发布时间: 2011-09-10

热门下载

更多