我在DLL中建了一个窗体,再在窗体中建了个线程,这个线程为什么不能访问窗体中的控件?!我用了两种方法建线程,第一种没反应,第二各(API),提示出错“内存不能为

  • 主题发起人 主题发起人 陆波
  • 开始时间 开始时间

陆波

Unregistered / Unconfirmed
GUEST, unregistred user!
我在DLL中建了一个窗体,再在窗体中建了个线程,这个线程为什么不能访问窗体中的控件?!我用了两种方法建线程,第一种没反应,第二各(API),提示出错“内存不能为READ” ( 积分: 100 )<br />我在DLL中建了一个窗体,再在窗体中建了个线程,这个线程为什么不能执行!我用了两种方法建线程,第一种没反应,第二各(API),提示出错“内存不能为READ”
我在DLL中建了一个窗体,(经测试是没问题了的!能在窗体上用各种控件,可是就是不能不能运行新建的线程!!!
)
窗体文件如下:
//================================form
unit test111;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,shellapi;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
//线程定义
type
TMyThread = class(TThread)
private
protected
procedure Execute;
override;
public
num1:integer;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function MyThreadFunc(P:pointer):Longint;stdcall;
begin
form1.Memo1.Lines.Add('API 运行线程') ;
end;
//=============================================
procedure TMyThread.Execute;
begin
case num1 of
1: form1.Memo1.Lines.Add('运行线程') ;
end;
freeonterminate:=true;
{ Place thread code here }
end;
//============================================
procedure TForm1.Button1Click(Sender: TObject);
var
mythread:tmythread;
begin
mythread:= tmythread.Create(true);
mythread.num1:=1;
mythread.Resume;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
hThread:Thandle;//定义一个句柄
ThreadID:DWord;
begin
//创建线程,同时线程函数被调用
hthread:=CreateThread(nil,0,@MyThreadfunc,nil,0,ThreadID);
if hThread=0 then
messagebox(Handle,'Didn’t Create a Thread',nil,MB_OK);
end;
end.
 
form1:=tform1.Create(nil) ;用NIL当参数的窗体要自己释放内存
还有你的TEST111是什么东西?就是一个窗体吗》??
在DLL中建窗体最好直接用API建
 
function MyThreadFunc(P:pointer):Longint;stdcall;
begin

form1.Memo1.Lines.Add('API 运行线程') ;
end;

这个函数怎么没有返回值??
 
begin
runform;
end.
怎么初始化就调用函数了
 
to 暗夜中独舞,
TEST111就是一个窗体,能正常显示!
//=====载入DLL就运行runform,建一个窗体(测试方便!)
begin
runform;
end.
//=====载入DLL就运行runform,建一个窗体(测试方便!)
问题是:-》再在窗体unit test111 中建了个线程,这个线程为什么不能执行!
 
begin

//里面是变量的初始化
end;
也就是说有可能你的runform还没有分配到内存
而你这时候运行runform 内存当然就读不到了
 
但是我的FORM能正常建立啊!在FORM中的其他操作也没问题啊!!!只是建的线程不执行!!注意,代码是在DLL中的,是“begin
end.
’ 而不是“begin
end;
”是“.”而不是“;”!
unit test111 在新建的Application中是没问题的!只是在DLL中有问题而已,
 
unit test111里面就建立窗体了 而不是begin
end.
里面的
beign
//
end.
的时候还没分配好内存
比如如果我们在一个工程里建立两个窗体
当工程运行的时候自动就建立好这两个窗体了,只不过只有Main窗体 show出来了,而调用另一个窗体的时候是show而不是create
所以你的form能正常建立
 
那么怎样建窗才行?这个窗体能显示出来,并能使用其中的其他操作啊!为什么就不能调用其中的线程?
 
用Win32 API在DLL中直接建窗体
具体的API我也忘记了 你百度一下
 
不行啊!!谁可帮我??窗体我建了,但窗体中不能运行新建的线程啊,窗体能SHOW,HIDE。。。。能在窗体上用各种控件,可是就是不能不能运行新建的线程!!!
 
新发现:以下代码有问题:
function MyThreadFunc(P:pointer):Longint;stdcall;
begin
form1.Memo1.Lines.Add('API 运行线程') ;//这一句不能执行!!!
messagebox(application.Handle,'这一句行!!',nil,MB_OK);//用这一句代替上一句代码能正常执行!! 为什么啊!!我要的是能处理FORM1中的控件啊!!
end;
 
你建立窗体的时候你继承TForm 还是 TForm1??
要不你就这样
先用API写个TForm1的类,然后在DLL中实例化这个类
 
我试了下 好象直接继承TForm的类确实显示不出TMemo
 
1. 在线程中访问VCL最好用Synchronize,或者用消息来传递显示信息
2. 在DLL中访问宿主程序的Form最好采用回调方式,或者把Form的句柄传送过去,用消息、共享内存等方式交换数据
3. 访问类的实例时,要确保实例已经创建。
 
我用了IdThreadComponent控件在创建的窗体上,用控件的ONRUN实现了对MENO1的访问!同样是多线程!不用自己建实例了!为什么用IdThreadComponent控件创建的线程就能访问form1的Memo1????
 
来自:lisongmagic, 时间:2007-3-11 17:10:35, ID:3679872
像dll中的窗体一般用模态窗体,这样其内存比较容易控制,而不要交给其主属性如application等处理,做个小例子供你参考一下:(已调试,运行ok)
unit DLLForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TfrmDLL = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmDLL: TfrmDLL;
procedure SynAPP(App:THandle);stdcall;
procedure ShowForm;stdcall;
implementation
uses Math;
{$R *.dfm}
procedure SynAPP(App:THandle );stdcall;
begin
Application.Handle := App;
end;

procedure ShowForm;stdcall;
begin
try
frmDLL := TfrmDLL.Create (Application);
try
frmDLL.ShowModal;
finally
frmDLL.Free;
end;
except
on E: Exceptiondo
MessageDlg ('Error in DLLForm: ' +
E.Message, mtError, [mbOK], 0);
end;
end;

procedure TfrmDLL.Button1Click(Sender: TObject);
begin
Color := RandomRange(0,255 * 255 * 255 );
end;

end.
*************************************************
library FormDLL;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
SysUtils,
Classes,
Forms,
DLLForm in 'DLLForm.pas' {frmDLL};

{$R *.res}
exports
SynAPP,ShowForm;
begin
end.

****************************************************************
unit testDLLForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
procedure SynAPP(App:THandle);stdcall;external 'FormDLL.dll';
procedure ShowForm;stdcall;external 'FormDLL.dll';
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
SynApp(Application.Handle );
ShowForm ;
end;

end.
 
其他地方弄过来的 给你参考下
 
VCL不是线程安全的,楼主应该自己先看看Delphi/Demo/Threads目录下的Demo文件。另外当你新建TThread对象的时候,有一段英文写的很详细,就是告诉你应该用什么方式同步线程访问VCL。
 
因为,,,哈哈哈哈,
因为当你的 Memo 想要执行 Add 时,你的线程已经没有了(运行并退出了)。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部