如何在delphi进行异步处理?我进行一个操作时候总是没有响应 ( 积分: 50 )

C

caoli

Unregistered / Unconfirmed
GUEST, unregistred user!
我写activex控件,需要和web service进行通信,只要可是连接web service直到接受到返回数据这段时间,ie都是没有响应的.只有在这个操作结束后,整个IE才能进行别的操作
我想主程序和提交接受数据做异步处理,但是不知道怎么做
具体的做法是什么,能不能给个例子?
 
我写activex控件,需要和web service进行通信,只要可是连接web service直到接受到返回数据这段时间,ie都是没有响应的.只有在这个操作结束后,整个IE才能进行别的操作
我想主程序和提交接受数据做异步处理,但是不知道怎么做
具体的做法是什么,能不能给个例子?
 
我用到如下的代码.如果直接建立一个标准的程序,这些代码一点问题没有.
但是如果用在activex form里面就出很多问题,请问哪位能指点一下:在activex from里面如何建立一个线程?

unit Unit1

interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons


type
TForm1 = class(TForm)
? UsedThread: TBitBtn

? NoUsedThread: TBitBtn

? procedure UsedThreadClick(Sender: TObject)

? procedure NoUsedThreadClick(Sender: TObject)

private
? { Private declarations }
public
? { Public declarations }
end


var
Form1: TForm1


implementation

{$R *.dfm}

function MyThreadFunc(P:pointer):Longint;stdcall

var
i:longint

DC:HDC

S:string

begin
DC:=GetDC(Form1.Handle)

for i:=0 to 500000 do begin
? S:=Inttostr(i)

? Textout(DC,10,10,Pchar(S),length(S))

end

ReleaseDC(Form1.Handle,DC)

end



procedure TForm1.UsedThreadClick(Sender: TObject)

var
hThread:Thandle;//定义一个句柄
ThreadID:DWord

begin
//创建线程,同时线程函数被调用
hthread:=CreateThread(nil,0,@MyThreadfunc,nil,0,ThreadID)

if hThread=0 then
messagebox(Handle,'Didn’tCreateaThread',nil,MB_OK)

end


procedure TForm1.NoUsedThreadClick(Sender: TObject)

begin
MyThreadfunc(nil)

//没有创建线程时,直接调用线程函数
end

end.
 
hThread:=CreateThread(nil,0,@MyThreadfunc,nil,0,ThreadID);
关键是这行出现错误,就是创建线程的时候,错误的类型是"Variable required"
哪位给提醒一下?
 
是编译不通过?
给你几个参考的东西

http://www.delphibbs.com/delphibbs/dispq.asp?LID=1374090

http://www.delphibbs.com/delphibbs/dispq.asp?LID=2334299
 
chenybin,非常感谢你的帮助
我看了两个帖子,关键的区别在于,我想在activex form中建立一个线程,而不是应用程序中建立.如果是应用程序中间里线程,是没有问题的.但是在activex form相同代码建立线程,确出现错误!!
请指点!谢谢
 
出错的行是这行:
hThread:=CreateThread(nil,0,@MyThreadfunc,nil,0,ThreadID);
出错时候,光标的位置是在第二个nil前面.错误信息是"Variable required"
 
要忙了,activex不好调试,我一般都采用写临时文件的方式,不过的编译都通不过就麻烦一点了,一点建议,供参考
 
不管怎样,谢谢你了
还希望其他大侠帮忙啊!
 
ThreadID 换个变量名看看,比如ThreadID1 之类的
 
还是一样的错误.
怀疑可能是activex form中取得function的指针方式不同,但是我不知道怎么取
 
还有就是,不太清楚如何在activex form里面声名这个线程函数
 
为什么不直接用TThread呢

我改动了以下,编译不出错了,结果可能会出错,你看看


声明 ……
TActiveFormX = class(TActiveForm, IActiveFormX)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
FEvents: IActiveFormXEvents;
procedure ActivateEvent(Sender: TObject);
procedure ClickEvent(Sender: TObject);
procedure CreateEvent(Sender: TObject);
procedure DblClickEvent(Sender: TObject);
procedure DeactivateEvent(Sender: TObject);
procedure DestroyEvent(Sender: TObject);
procedure KeyPressEvent(Sender: TObject
var Key: Char);
procedure PaintEvent(Sender: TObject);
function MyThreadFunc(P: pointer): Longint
stdcall;
protected


定义……

function [blue]TActiveFormX[/blue].MyThreadFunc(P:pointer):Longint;stdcall;
var
i:longint;
DC:HDC;
S:string;
begin

DC:=GetDC(Self.Handle);
for i:=0 to 500000 do begin
S:=Inttostr(i);
Textout(DC,10,10,Pchar(S),length(S));
end;
ReleaseDC(Self.Handle,DC);
end;


procedure TActiveFormX.Button1Click(Sender: TObject);
var
hThread:Thandle;//定义一个句柄
ThreadID:DWord;
begin
//创建线程,同时线程函数被调用
hthread:=CreateThread(nil,0[blue],@TActiveFormX.MyThreadfunc[/blue],nil,0,ThreadID);
if hThread=0 then
messagebox(Handle,'Didn’tCreateaThread',nil,MB_OK);
end;

procedure TActiveFormX.Button2Click(Sender: TObject);
begin
MyThreadfunc(nil);
//没有创建线程时,直接调用线程函数
end;
 
确实是这样的,编译没问题,结果出错,ie直接产生错误关闭了!
直接用TThread?请给个例子?我不知道怎么用啊?
 
网上很多的,论坛里面也有,自己搜索一下吧

建立一个线程类 TMyThread = class(TThread);
覆盖它的Execute方法,这里就是线程的运行主体了,

-----------------------------转自网络

第一、什么是进程?什么是线程?
我们知道,Windows95、98、2000、XP操作系统支持两种形式的多任务。第一种类型是基于进程的机制,这也是Windows从一开始就支持的多处理类型。进程本质上是指正在执行着的程序,它是应用程序的执行实例。每个进程是由私有的虚拟地址空间、代码、数据和其他各种系统资源组成的。进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭。在基于进程的多任务环境下,两个至多个进程可以并发地执行。第二种类型是基于线程(thread)的机制,基于线程的多任务对于多数Windows用户和程序员而言是一个崭新的概念。线程是指进程中的一个执行流,它是进程内部的一个执行单元(如可以是一个函数或一个活跃的类对象等)。系统创建好进程后,实际上就启动执行了该进程的主执行线程。主执行线程终止了,进程也就随之终止。
每一个进程至少有一个线程(即主执行线程,它无需由用户去主动创建,是由系统将应用程序启动后创建的),用户根据需要在应用程序中创建其他线程,多个线程并发地运行在同一个进程中。一个进程中的所有线程都在该进程的虚拟地址空间中,使用这些虚拟地址空间、全局变量和系统资源,所以线程之间的通讯要比进程之间的通讯容易得多。
多线程设计在实际中的使用较为广泛。在Windows 95/98/NT/XP中,每一个进程拥有至少一个线程,允许同时执行两个或多个线程。并由我们的程序控制它们。基于线程的多任务允许同一程序的不同部分(线程)并发地执行。这样,程序员就能够写出非常高效的程序,因为程序员能够定义执行线程并管理程序的执行方式,能够完全地控制程序片段的执行。例如,可以在一个程序中指定一个线程执行文件排序工作,指定另外一个线程负责收集来自某个远程资源的信息,指定又一线程完成用户输入的工作。因为处于多线程多任务环境,每一线程都能够并发地执行,这样就能充分地利用CPU时间。基于线程的多任务使得同步功能特征显得更为重要。既然多个线程(及进程)可以并发执行,那么必须适当地协调线程间的执行顺序以使其能同步访问共享资源与内存,从而使程序编写起来显得更加复杂。Windows系统增加了一个完整的子系统以支持同步机制,其中的一些关键特征不在本文讨论范围之内。

第二、为什么要使用多线程?
在很多情况下,需要采用多线程技术进行程序设计。例如,常用的字处理软件Word,当输入文字的时候,Word同时进行拼写和语法的检验,也就是将文档中的词语与词库中的词语进行比较,并对文档中的语句进行语法分析。这些操作都比较耗费时间,但是我们在使用Word的时候并没有感觉到输入过程有明显的滞后现象。这里Word就采用了多线程技术,其中一个线程接收输入,另一个线程进行拼写和语法的检验。
一般说来,使用多线程具有以下优点:
1.由于CPU处理速度比较快,可以使用户在做一件事情的时候还可以做另外一件事。比如在有些杀毒软件杀毒的时候,还可以通过菜单来浏览病毒清单。
2.在多个CPU的情况下,可以充分利用硬件的优势,将一个大任务分成几个小任务由不同的CPU来完成。
3.可以为每个线程设置优先级,调整工作的进度。
不过,多线程在帮助解决某些问题的同时,也要注意一些新的问题:
1.滥用线程容易使程序变得支离破碎,增加程序编写的复杂度。
2.在多个线程对数据进行读和写操作的时候,数据的安全有效性可能会遭到破坏。
3.有时如果频繁地在线程间切换会耗费大量的CPU时间,使得整个工作的处理时间延长了。
因此,进行多线程的程序设计,要充分考虑到设计的可行性和安全性,发挥出并行运行的高效性,最大限度地提高程序的效率。

第三、如何开发多线程的程序?
编写基于线程的程序,既可以使用Windows提供的API函数,也可以使用Delphi提供的线程对象。而使用Delphi的线程对象(TThread对象),则可使编写线程程序变得简单、高效。TThread对象提供了许多特性和方法(成员函数),它类将Windows API函数中关于多线程方面的函数封装到了一起,你只要根据工作需要对这些函数或方法进行重写,即可在程序中实现多线程机制。Tthread类是TObject对象的直接派生类。与其它大多数Delphi类和构件不同的是,你不能在程序中直接使用该对象,而必须从Tthread类产生一个新的派生类,并对需要使用的方法进行重写,以重载(Override)Tthread类的方法。
利用TThread类来编写多线程应用程序的一般步骤如下:
1.从TThread类派生出一个新的线程类。
2.创建线程对象。
3.设置线程对象的属性,比如优先级等。
4.根据具体情况挂起或唤醒线程。
5.结束线程。
在Delphi中,你既可以通过直接书写线程代码来创建线程,也可以Delphi的File菜单的New命令向当前项目文件加入一个线程对象来实现。两者结果都一样,都是产生一个Tthread类的派生类,下面就使用后一种方法进行说明。
选择File菜单的New命令,打开New Items对话框,选择New页标签下的Thread Object图标(如图1所示),打开New Thread Object对话框(如图2所示)。在New Thread Object对话框的Class Name编辑框,输入创建线程的类名,然后选择OK按钮,则Delphi自动生成一个新的代码文件,该代码文件即为新线程类的代码文件
unit Unit2;
interface
uses
Classes;
type
test = class(TThread)
private
{ Private declarations }
protected
procedure Execute
override;
end;
implementation
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure test.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end
}
{ test }
procedure test.Execute;
begin
{ Place thread code here }
end;
end.
该代码文件生成一个线程类的派生类,并提供了需要派生类覆盖的方法Execute说明。文件中还包含如何编写处理VCL构件方法的说明信息。下面就可以根据特殊的需要修改新的线程类了。
TThread类有一个构造函数Create,函数原型如下:constructor Create(CreateSuspended: Boolean);
其中参数CreateSuspended为一个布尔类型的变量。如果设置为False,则线程对象创建后立即调用TThread类的另一个过程Execute,也就是立即开始执行线程的操作;如果设置为True,则线程对象创建后,要调用过程Resume后线程的操作才开始。可以在TThread类的派生类中重新定义Create构造函数,用来对派生类中的一些属性进行初始化。
我们可以自己定义TThread类的派生类中的Execute过程,过程Execute中的代码就是线程要做的工作。如果Execute过程执行完毕,则该线程就结束了,并释放线程占用的栈空间。通常在Execute过程的重载函数中要有一个repeat…until语句,如:
procedure TSquareThread.Execute;
begin
……
repeat
…… // 具体的操作
until Terminated
// 判断是否应该结束线程
……
end;
其中Terminated为线程类的一个属性,用来标志是否应该结束线程
 
顶部