beginthread(在Delphi里怎样判断线程是否结束)
专栏
2024-04-06 06:06
235
目录- beginthread,在Delphi里怎样判断线程是否结束?
- 中Invoke和BeginInvoke的区别?
- 怎么进行socket通信?
- nm使用方法?
- 使用多线程的几种方式示例详解?
- 唱起歌儿快乐多英文版?
- mfc添加主副线程源码?
beginthread,在Delphi里怎样判断线程是否结束?
判断线程是否存在使用:ifAssigned(workthread)thenbegin//doworkend;释放线程使用:可以使线程对象自动释放,使用:workthread.FreeOnTerminate:=True;如果想自己释放线程则应该先判断线程是否存在和是否结束然后再释放,使用:ifAssigned(workthread)and(notworkthread.Finished)thenbegin//workthread.terminate;//停止线程//workthread.suspended;//使线程暂停以上两种都可以,如果使用Terminate则应该等待线程完全结束workthread.Free;//释放线程end;
中Invoke和BeginInvoke的区别?
区别在于Invoke是同步,BeginInvoke是异步。
打个比方(伪代码),后台线程中需要通知UI界面进行刷新
new Thread() { /* 比如读取数据库的方法,比较耗时; var data = GetData(); 读取完成后通知UI线程, this.Invoke(data); //如果GetData方法是同步方法,则用Invoke回调 //this.BeginInvoke(data); //如果GetData是异步方法,则用BeginInvoke回掉 }
在.NET 4.5或者更早的版本中,如果异步方法使用Invoke也是可以编译通过的,同时在Debug的时候也不会有问题,但是发布出去就会出异常。同步方法用BeginInvoke也是如此。
之前项目中出现过一次异步方法用Invoke回调,总是出异常,而且vs调试了很久都不知道问题出在哪里, 所以一定要弄清楚后台运行的方式到底是同步还是异步。
怎么进行socket通信?
设计思路
本例包括一个服务器端程序和一个客户端程序。客户端程序可以放到多个计算机上运行,同时与服务器端进行连接通信。
本例的重点,一是演示客户端与服务器端如何通信;二是当有多个客户端同时连接到服务器端时,服务器端如何识别每个客户端,并对请求给出相应的回复。为了保证一个客户端断开连接时不影响其它客户端与服务器端的通信,同时保证服务器端能够正确回复客户端的请求,在本例中声明了一个记录类型:
type
client_record=record
CHandle:integer;//客户端套接字句柄
Csocket:TCustomWinSocket;//客户端套接字
CName:string;//客户端计算机名称
CAddress:string;//客户端计算机IP地址
CUsed:boolean;//客户端联机标志
end;
利用这个记录类型数据保存客户端的信息,同时保存当前客户端的连接状态。其中,CHandle保存客户端套接字句柄,以便准确定位每个与服务器端保持连接的客户端;Csocket保存客户端套接字,通过它可以对客户端进行回复。Cused记录当前客户端是否与服务器端保持连接。
下面对组件ServerSocket和ClientSocket的属性设置简单说明。
ServerSocket的属性:
·Port,是通信的端口,必须设置。在本例中设置为1025;
·ServerTypt,服务器端读写信息类型,设置为stNonBlocking表示异步读写信息,本例中采用这种方式。
·ThreadCacheSize,客户端的最大连接数,就是服务器端最多允许多少客户端同时连接。本例采用默认值10。
其它属性采用默认设置即可。
ClientSocket的属性:
·Port,是通信的端口,必须与服务器端的设置相同。在本例中设置为1025;
·ClientType,客户端读写信息类型,应该与服务器端的设置相同,为stNonBlocking表示异步读写信息。
·Host,客户端要连接的服务器的IP地址。必须设置,当然也可以在代码中动态设置。
其它属性采用默认设置即可。
程序源代码:
·服务器端源码(uServerMain.pas):
unituServerMain;
interface
uses
Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,
ScktComp,ToolWin,ComCtrls,ExtCtrls,StdCtrls,Buttons;
const
CMax=10;//客户端最大连接数
type
client_record=record
CHandle:integer;//客户端套接字句柄
CSocket:TCustomWinSocket;//客户端套接字
CName:string;//客户端计算机名称
CAddress:string;//客户端计算机IP地址
CUsed:boolean;//客户端联机标志
end;
type
TfrmServerMain=class(TForm)
ServerSocket:TServerSocket;
ControlBar1:TControlBar;
ToolBar1:TToolBar;
tbConnect:TToolButton;
tbClose:TToolButton;
tbDisconnected:TToolButton;
Edit1:TEdit;
Memo1:TMemo;
StatusBar:TStatusBar;
proceduretbConnectClick(Sender:TObject);
proceduretbDisconnectedClick(Sender:TObject);
procedureServerSocketClientRead(Sender:TObject;Socket:TCustomWinSocket);
procedureServerSocketListen(Sender:TObject;Socket:TCustomWinSocket);
procedureServerSocketClientConnect(Sender:TObject;Socket:TCustomWinSocket);
procedureServerSocketClientDisconnect(Sender:TObject;Socket:TCustomWinSocket);
proceduretbCloseClick(Sender:TObject);
procedureFormCreate(Sender:TObject);
procedureFormClose(Sender:TObject;varAction:TCloseAction);
procedureServerSocketGetSocket(Sender:TObject;Socket:Integer;
varClientSocket:TServerClientWinSocket);
procedureServerSocketClientError(Sender:TObject;
Socket:TCustomWinSocket;ErrorEvent:TErrorEvent;
varErrorCode:Integer);
private
{
Privatedeclarations
}
public
{
Publicdeclarations
}
session:array[0..CMax]ofclient_record;//客户端连接数组
Sessions:integer;//客户端连接数
end;
var
frmServerMain:TfrmServerMain;
implementation
{$R*.DFM}
//打开套接字连接,并使套接字进入监听状态
procedureTfrmServerMain.tbConnectClick(Sender:TObject);
begin
ServerSocket.Open;
end;
//关闭套接字连接,不再监听客户端的请求
procedureTfrmServerMain.tbDisconnectedClick(Sender:TObject);
begin
ServerSocket.Close;
StatusBar.Panels[0].Text:='服务器套接字连接已经关闭,无法接受客户端的连接请求.';
end;
//从客户端读取信息
procedureTfrmServerMain.ServerSocketClientRead(Sender:TObject;Socket:TCustomWinSocket);
var
i:integer;
begin
//将从客户端读取的信息添加到Memo1中
Memo1.Lines.Add(Socket.ReceiveText);
fori:=0tosessionsdo
begin
//取得匹配的客户端
ifsession[i].CHandle=Socket.SocketHandlethen
begin
session[i].CSocket.SendText('回复客户端'+session[i].CAddress+'==>'+Edit1.Text);
end;
end;
end;
//服务器端套接字进入监听状态,以便监听客户端的连接
procedureTfrmServerMain.ServerSocketListen(Sender:TObject;Socket:TCustomWinSocket);
begin
StatusBar.Panels[0].Text:='等待客户端连接...';
end;
//当客户端连接到服务器端以后
procedureTfrmServerMain.ServerSocketClientConnect(Sender:TObject;
Socket:TCustomWinSocket);
var
i,j:integer;
begin
j:=/uploads/title/20240101/659240f52a64a.jpg1;
fori:=0tosessionsdo
begin
//在原有的客户端连接数组中有中断的客户端连接
ifnotsession[i].CUsedthen
begin
session[i].CHandle:=Socket.SocketHandle;//客户端套接字句柄
session[i].CSocket:=Socket;//客户端套接字
session[i].CName:=Socket.RemoteHost;//客户端计算机名称
session[i].CAddress:=Socket.RemoteAddress;//客户端计算机IP
session[i].CUsed:=True;//连接数组当前位置已经占用
Break;
end;
j:=i;
end;
ifj=sessionsthen
begin
inc(sessions);
session[j].CHandle:=Socket.SocketHandle;
session[j].CSocket:=Socket;
session[j].CName:=Socket.RemoteHost;
session[j].CAddress:=Socket.RemoteAddress;
session[j].CUsed:=True;
end;
StatusBar.Panels[0].Text:='客户端'+Socket.RemoteHost+'已经连接';
end;
//当客户端断开连接时
procedureTfrmServerMain.ServerSocketClientDisconnect(Sender:TObject;
Socket:TCustomWinSocket);
var
i:integer;
begin
fori:=0tosessionsdo
begin
ifsession[i].CHandle=Socket.SocketHandlethen
begin
session[i].CHandle:=0;
session[i].CUsed:=False;
Break;
end;
end;
StatusBar.Panels[0].Text:='客户端'+Socket.RemoteHost+'已经断开';
end;
//关闭窗口
procedureTfrmServerMain.tbCloseClick(Sender:TObject);
begin
Close;
end;
procedureTfrmServerMain.FormCreate(Sender:TObject);
begin
sessions:=0;
end;
procedureTfrmServerMain.FormClose(Sender:TObject;varAction:TCloseAction);
begin
ServerSocket.Close;
end;
//当客户端正在与服务器端连接时
procedureTfrmServerMain.ServerSocketGetSocket(Sender:TObject;
Socket:Integer;varClientSocket:TServerClientWinSocket);
begin
StatusBar.Panels[0].Text:='客户端正在连接...';
end;
//客户端发生错误
procedureTfrmServerMain.ServerSocketClientError(Sender:TObject;
Socket:TCustomWinSocket;ErrorEvent:TErrorEvent;
varErrorCode:Integer);
begin
StatusBar.Panels[0].Text:='客户端'+Socket.RemoteHost+'发生错误!';
ErrorCode:=0;
end;
end.
nm使用方法?
nm基本用法命令
nm用来列出目标文件的符号清单。下面是nm命令的格式:
nm[/uploads/title/20240101/659240f52a64a.jpga|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgdebug/uploads/title/20240101/659240f52a64a.jpgsyms][/uploads/title/20240101/659240f52a64a.jpgg|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgextern/uploads/title/20240101/659240f52a64a.jpgonly][/uploads/title/20240101/659240f52a64a.jpgB]
[/uploads/title/20240101/659240f52a64a.jpgC|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgdemangle][/uploads/title/20240101/659240f52a64a.jpgD|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgdynamic][/uploads/title/20240101/659240f52a64a.jpgs|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgprint/uploads/title/20240101/659240f52a64a.jpgarmap]
[/uploads/title/20240101/659240f52a64a.jpgo|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgprint/uploads/title/20240101/659240f52a64a.jpgfile/uploads/title/20240101/659240f52a64a.jpgname][/uploads/title/20240101/659240f52a64a.jpgn|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgnumeric/uploads/title/20240101/659240f52a64a.jpgsort] 输出符号所对应的库的名字,在查找符号在那个库中被定义时比较有用
[/uploads/title/20240101/659240f52a64a.jpgp|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgno/uploads/title/20240101/659240f52a64a.jpgsort][/uploads/title/20240101/659240f52a64a.jpgr|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgreverse/uploads/title/20240101/659240f52a64a.jpgsort][/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgsize/uploads/title/20240101/659240f52a64a.jpgsort]
[/uploads/title/20240101/659240f52a64a.jpgu|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgundefined/uploads/title/20240101/659240f52a64a.jpgonly][/uploads/title/20240101/659240f52a64a.jpgl|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgline/uploads/title/20240101/659240f52a64a.jpgnumbers][/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpghelp]
[/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgversion][/uploads/title/20240101/659240f52a64a.jpgtradix|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgradix=radix]
[/uploads/title/20240101/659240f52a64a.jpgP|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgportability][/uploads/title/20240101/659240f52a64a.jpgfformat|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgformat=format]
[/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgtarget=bfdname][objfile...]
如果没有为nm命令指出目标文件,则nm假定目标文件是a.out。下面列出该命令的任选项,大部分支持“/uploads/title/20240101/659240f52a64a.jpg”开头的短格式和“/uploads/title/20240101/659240f52a64a.jpg“开头的长格式。
/uploads/title/20240101/659240f52a64a.jpgA、/uploads/title/20240101/659240f52a64a.jpgo或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgprint/uploads/title/20240101/659240f52a64a.jpgfile/uploads/title/20240101/659240f52a64a.jpgname:在找到的各个符号的名字前加上文件名,而不是在此文件的所有符号前只出现文件名一次。
例如nmlibtest.a的输出如下:
CPThread.o:
00000068TMain__8CPThreadPv
00000038TStart__8CPThread
00000014T_._8CPThread
00000000T__8CPThread
00000000?__FRAME_BEGIN__
…………………………………
则nm/uploads/title/20240101/659240f52a64a.jpgA的输出如下:
libtest.a:CPThread.o:00000068TMain__8CPThreadPv
libtest.a:CPThread.o:00000038TStart__8CPThread
libtest.a:CPThread.o:00000014T_._8CPThread
libtest.a:CPThread.o:00000000T__8CPThread
libtest.a:CPThread.o:00000000?__FRAME_BEGIN__
…………………………………………………………..
/uploads/title/20240101/659240f52a64a.jpga或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgdebug/uploads/title/20240101/659240f52a64a.jpgsyms:显示调试符号。
/uploads/title/20240101/659240f52a64a.jpgB:等同于/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgformat=bsd,用来兼容MIPS的nm。
/uploads/title/20240101/659240f52a64a.jpgC或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgdemangle:将低级符号名解码(demangle)成用户级名字。这样可以使得C++函数名具有可读性。
/uploads/title/20240101/659240f52a64a.jpgD或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgdynamic:显示动态符号。该任选项仅对于动态目标(例如特定类型的共享库)有意义。
/uploads/title/20240101/659240f52a64a.jpgfformat:使用format格式输出。format可以选取bsd、sysv或posix,该选项在GNU的nm中有用。默认为bsd。
/uploads/title/20240101/659240f52a64a.jpgg或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgextern/uploads/title/20240101/659240f52a64a.jpgonly:仅显示外部符号。
/uploads/title/20240101/659240f52a64a.jpgn、/uploads/title/20240101/659240f52a64a.jpgv或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgnumeric/uploads/title/20240101/659240f52a64a.jpgsort:按符号对应地址的顺序排序,而非按符号名的字符顺序。
/uploads/title/20240101/659240f52a64a.jpgp或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgno/uploads/title/20240101/659240f52a64a.jpgsort:按目标文件中遇到的符号顺序显示,不排序。
/uploads/title/20240101/659240f52a64a.jpgP或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgportability:使用POSIX.2标准输出格式代替默认的输出格式。等同于使用任选项/uploads/title/20240101/659240f52a64a.jpgfposix。
/uploads/title/20240101/659240f52a64a.jpgs或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgprint/uploads/title/20240101/659240f52a64a.jpgarmap:当列出库中成员的符号时,包含索引。索引的内容包含:哪些模块包含哪些名字的映射。
/uploads/title/20240101/659240f52a64a.jpgr或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgreverse/uploads/title/20240101/659240f52a64a.jpgsort:反转排序的顺序(例如,升序变为降序)。
/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgsize/uploads/title/20240101/659240f52a64a.jpgsort:按大小排列符号顺序。该大小是按照一个符号的值与它下一个符号的值进行计算的。
/uploads/title/20240101/659240f52a64a.jpgtradix或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgradix=radix:使用radix进制显示符号值。radix只能为“d”表示十进制、“o”表示八进制或“x”表示十六进制。
/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgtarget=bfdname:指定一个目标代码的格式,而非使用系统的默认格式。
/uploads/title/20240101/659240f52a64a.jpgu或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgundefined/uploads/title/20240101/659240f52a64a.jpgonly:仅显示没有定义的符号(那些外部符号)。
/uploads/title/20240101/659240f52a64a.jpgl或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgline/uploads/title/20240101/659240f52a64a.jpgnumbers:对每个符号,使用调试信息来试图找到文件名和行号。对于已定义的符号,查找符号地址的行号。对于未定义符号,查找指向符号
重定位入口的行号。如果可以找到行号信息,显示在符号信息之后。
/uploads/title/20240101/659240f52a64a.jpgV或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgversion:显示nm的版本号。
/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpghelp:显示nm的任选项。
ar cs libmy.a//创建一个库
ar rs libmy.a 1.o//增加一个模块
ar t libmy.a//显示库里的模块
ar d libmy.a 1.o//删除一个模块
nm命令的输出:
关于符号的类型,这里我们再多讨论一下。符号的类型是以一个字母的形式显示的,小写字母表示这个符号是本地(local)的,而大写字母则表示这个
符号是 全局的(global,externel)。
一般来说,类型有一下几种:T、D、B、U、W。各自的含义如下:
T表示在代码段中定义的一般变量符号;
D表示是初始化过的数据段;
B表示初始化的数据段;
U表示没有定义的,在这个库里面使用了,但是在其他库中定义的符号;
W,weak的缩写,表示如果其他函数库中也有对这个符号的定义,则其他符号的定义可以覆盖这个定义。
使用多线程的几种方式示例详解?
多线程使用的主要的几种形式:
1)使用Thread类创建一个新线程
static void Main(string[] args){ Thread thread = new Thread(delegate(){ for (int i = 0; i <= 10; i++){ Console.WriteLine(Thread.CurrentThread.Name + ":" + i); Thread.Sleep(100); } }); thread.Name = "t1 thread"; thread.Start(); Console.WriteLine("TO DO SOMETHING..."); Console.ReadKey(true);}
2)使用async与await关键字配合使用
static void Main(string[] args){ Console.WriteLine("Main method start..."); Foo(); Console.WriteLine("TO DO SOMETHING..."); Console.WriteLine("Main method end..."); Console.ReadKey(true);} async static void Foo(){ Console.WriteLine("Foo method start."); await Task.Delay(2000); Console.WriteLine("Foo method end.");}
3)使用委托内置的实例方法BeginInvoke实现异步编程
static void Main(string[] args){ Func sum = (x, y) =>{ Thread.Sleep(2000); return x + y; }; sum.BeginInvoke(10, 5,(IAsyncResult asyncResult)=> { Console.WriteLine("callback method."); }, null); Console.WriteLine("TO DO SOMETHING..."); Console.ReadKey(true);}
唱起歌儿快乐多英文版?
DoReMi 唱起歌儿快乐多。英文版歌词:
let's start at the very beginning,a very good place to start.
when you read you begin with a/uploads/title/20240101/659240f52a64a.jpgb/uploads/title/20240101/659240f52a64a.jpgc,when you sing you begin with do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi.
do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi, do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi,the first three notes just happen to be.
do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi, do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi,do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi/uploads/title/20240101/659240f52a64a.jpgfa/uploads/title/20240101/659240f52a64a.jpgso/uploads/title/20240101/659240f52a64a.jpgla/uploads/title/20240101/659240f52a64a.jpgti,let's see if i can make it easy.
doe, a deer, a female deer,ray, a drop of golden sun.
me, a name i call myself,far, a long, long way to run.
sew, a needle pulling thread,la, a note to follow sew.
tea, a drink with jam and bread,that will bring us back to do (oh/uploads/title/20240101/659240f52a64a.jpgoh/uploads/title/20240101/659240f52a64a.jpgoh)ha.
do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi/uploads/title/20240101/659240f52a64a.jpgfa/uploads/title/20240101/659240f52a64a.jpgso/uploads/title/20240101/659240f52a64a.jpgla/uploads/title/20240101/659240f52a64a.jpgti/uploads/title/20240101/659240f52a64a.jpgdo.
mfc添加主副线程源码?
这个问题不太明确,可能需要具体的情境或者细节上的说明。如果是关于 MFC 编程中如何添加主线程和副线程的源码,那么可以开启一个主线程,并且在主线程中使用 AfxBeginThread() 函数创建一个新的副线程,并且在副线程中编写相应的代码。具体的源码需要结合具体的需求和情境进行编写,具体步骤和细节可以查看 MFC 编程相关文档或者教程。
本站涵盖的内容、图片等数据系网络收集,部分未能与原作者取得联系。若涉及版权问题,请联系ynstorm@foxmail.com进行删除!
- beginthread,在Delphi里怎样判断线程是否结束?
- 中Invoke和BeginInvoke的区别?
- 怎么进行socket通信?
- nm使用方法?
- 使用多线程的几种方式示例详解?
- 唱起歌儿快乐多英文版?
- mfc添加主副线程源码?
beginthread,在Delphi里怎样判断线程是否结束?
判断线程是否存在使用:ifAssigned(workthread)thenbegin//doworkend;释放线程使用:可以使线程对象自动释放,使用:workthread.FreeOnTerminate:=True;如果想自己释放线程则应该先判断线程是否存在和是否结束然后再释放,使用:ifAssigned(workthread)and(notworkthread.Finished)thenbegin//workthread.terminate;//停止线程//workthread.suspended;//使线程暂停以上两种都可以,如果使用Terminate则应该等待线程完全结束workthread.Free;//释放线程end;
中Invoke和BeginInvoke的区别?
区别在于Invoke是同步,BeginInvoke是异步。
打个比方(伪代码),后台线程中需要通知UI界面进行刷新
new Thread() { /* 比如读取数据库的方法,比较耗时; var data = GetData(); 读取完成后通知UI线程, this.Invoke(data); //如果GetData方法是同步方法,则用Invoke回调 //this.BeginInvoke(data); //如果GetData是异步方法,则用BeginInvoke回掉 }
在.NET 4.5或者更早的版本中,如果异步方法使用Invoke也是可以编译通过的,同时在Debug的时候也不会有问题,但是发布出去就会出异常。同步方法用BeginInvoke也是如此。
之前项目中出现过一次异步方法用Invoke回调,总是出异常,而且vs调试了很久都不知道问题出在哪里, 所以一定要弄清楚后台运行的方式到底是同步还是异步。
怎么进行socket通信?
设计思路
本例包括一个服务器端程序和一个客户端程序。客户端程序可以放到多个计算机上运行,同时与服务器端进行连接通信。
本例的重点,一是演示客户端与服务器端如何通信;二是当有多个客户端同时连接到服务器端时,服务器端如何识别每个客户端,并对请求给出相应的回复。为了保证一个客户端断开连接时不影响其它客户端与服务器端的通信,同时保证服务器端能够正确回复客户端的请求,在本例中声明了一个记录类型:
type
client_record=record
CHandle:integer;//客户端套接字句柄
Csocket:TCustomWinSocket;//客户端套接字
CName:string;//客户端计算机名称
CAddress:string;//客户端计算机IP地址
CUsed:boolean;//客户端联机标志
end;
利用这个记录类型数据保存客户端的信息,同时保存当前客户端的连接状态。其中,CHandle保存客户端套接字句柄,以便准确定位每个与服务器端保持连接的客户端;Csocket保存客户端套接字,通过它可以对客户端进行回复。Cused记录当前客户端是否与服务器端保持连接。
下面对组件ServerSocket和ClientSocket的属性设置简单说明。
ServerSocket的属性:
·Port,是通信的端口,必须设置。在本例中设置为1025;
·ServerTypt,服务器端读写信息类型,设置为stNonBlocking表示异步读写信息,本例中采用这种方式。
·ThreadCacheSize,客户端的最大连接数,就是服务器端最多允许多少客户端同时连接。本例采用默认值10。
其它属性采用默认设置即可。
ClientSocket的属性:
·Port,是通信的端口,必须与服务器端的设置相同。在本例中设置为1025;
·ClientType,客户端读写信息类型,应该与服务器端的设置相同,为stNonBlocking表示异步读写信息。
·Host,客户端要连接的服务器的IP地址。必须设置,当然也可以在代码中动态设置。
其它属性采用默认设置即可。
程序源代码:
·服务器端源码(uServerMain.pas):
unituServerMain;
interface
uses
Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,
ScktComp,ToolWin,ComCtrls,ExtCtrls,StdCtrls,Buttons;
const
CMax=10;//客户端最大连接数
type
client_record=record
CHandle:integer;//客户端套接字句柄
CSocket:TCustomWinSocket;//客户端套接字
CName:string;//客户端计算机名称
CAddress:string;//客户端计算机IP地址
CUsed:boolean;//客户端联机标志
end;
type
TfrmServerMain=class(TForm)
ServerSocket:TServerSocket;
ControlBar1:TControlBar;
ToolBar1:TToolBar;
tbConnect:TToolButton;
tbClose:TToolButton;
tbDisconnected:TToolButton;
Edit1:TEdit;
Memo1:TMemo;
StatusBar:TStatusBar;
proceduretbConnectClick(Sender:TObject);
proceduretbDisconnectedClick(Sender:TObject);
procedureServerSocketClientRead(Sender:TObject;Socket:TCustomWinSocket);
procedureServerSocketListen(Sender:TObject;Socket:TCustomWinSocket);
procedureServerSocketClientConnect(Sender:TObject;Socket:TCustomWinSocket);
procedureServerSocketClientDisconnect(Sender:TObject;Socket:TCustomWinSocket);
proceduretbCloseClick(Sender:TObject);
procedureFormCreate(Sender:TObject);
procedureFormClose(Sender:TObject;varAction:TCloseAction);
procedureServerSocketGetSocket(Sender:TObject;Socket:Integer;
varClientSocket:TServerClientWinSocket);
procedureServerSocketClientError(Sender:TObject;
Socket:TCustomWinSocket;ErrorEvent:TErrorEvent;
varErrorCode:Integer);
private
{
Privatedeclarations
}
public
{
Publicdeclarations
}
session:array[0..CMax]ofclient_record;//客户端连接数组
Sessions:integer;//客户端连接数
end;
var
frmServerMain:TfrmServerMain;
implementation
{$R*.DFM}
//打开套接字连接,并使套接字进入监听状态
procedureTfrmServerMain.tbConnectClick(Sender:TObject);
begin
ServerSocket.Open;
end;
//关闭套接字连接,不再监听客户端的请求
procedureTfrmServerMain.tbDisconnectedClick(Sender:TObject);
begin
ServerSocket.Close;
StatusBar.Panels[0].Text:='服务器套接字连接已经关闭,无法接受客户端的连接请求.';
end;
//从客户端读取信息
procedureTfrmServerMain.ServerSocketClientRead(Sender:TObject;Socket:TCustomWinSocket);
var
i:integer;
begin
//将从客户端读取的信息添加到Memo1中
Memo1.Lines.Add(Socket.ReceiveText);
fori:=0tosessionsdo
begin
//取得匹配的客户端
ifsession[i].CHandle=Socket.SocketHandlethen
begin
session[i].CSocket.SendText('回复客户端'+session[i].CAddress+'==>'+Edit1.Text);
end;
end;
end;
//服务器端套接字进入监听状态,以便监听客户端的连接
procedureTfrmServerMain.ServerSocketListen(Sender:TObject;Socket:TCustomWinSocket);
begin
StatusBar.Panels[0].Text:='等待客户端连接...';
end;
//当客户端连接到服务器端以后
procedureTfrmServerMain.ServerSocketClientConnect(Sender:TObject;
Socket:TCustomWinSocket);
var
i,j:integer;
begin
j:=/uploads/title/20240101/659240f52a64a.jpg1;
fori:=0tosessionsdo
begin
//在原有的客户端连接数组中有中断的客户端连接
ifnotsession[i].CUsedthen
begin
session[i].CHandle:=Socket.SocketHandle;//客户端套接字句柄
session[i].CSocket:=Socket;//客户端套接字
session[i].CName:=Socket.RemoteHost;//客户端计算机名称
session[i].CAddress:=Socket.RemoteAddress;//客户端计算机IP
session[i].CUsed:=True;//连接数组当前位置已经占用
Break;
end;
j:=i;
end;
ifj=sessionsthen
begin
inc(sessions);
session[j].CHandle:=Socket.SocketHandle;
session[j].CSocket:=Socket;
session[j].CName:=Socket.RemoteHost;
session[j].CAddress:=Socket.RemoteAddress;
session[j].CUsed:=True;
end;
StatusBar.Panels[0].Text:='客户端'+Socket.RemoteHost+'已经连接';
end;
//当客户端断开连接时
procedureTfrmServerMain.ServerSocketClientDisconnect(Sender:TObject;
Socket:TCustomWinSocket);
var
i:integer;
begin
fori:=0tosessionsdo
begin
ifsession[i].CHandle=Socket.SocketHandlethen
begin
session[i].CHandle:=0;
session[i].CUsed:=False;
Break;
end;
end;
StatusBar.Panels[0].Text:='客户端'+Socket.RemoteHost+'已经断开';
end;
//关闭窗口
procedureTfrmServerMain.tbCloseClick(Sender:TObject);
begin
Close;
end;
procedureTfrmServerMain.FormCreate(Sender:TObject);
begin
sessions:=0;
end;
procedureTfrmServerMain.FormClose(Sender:TObject;varAction:TCloseAction);
begin
ServerSocket.Close;
end;
//当客户端正在与服务器端连接时
procedureTfrmServerMain.ServerSocketGetSocket(Sender:TObject;
Socket:Integer;varClientSocket:TServerClientWinSocket);
begin
StatusBar.Panels[0].Text:='客户端正在连接...';
end;
//客户端发生错误
procedureTfrmServerMain.ServerSocketClientError(Sender:TObject;
Socket:TCustomWinSocket;ErrorEvent:TErrorEvent;
varErrorCode:Integer);
begin
StatusBar.Panels[0].Text:='客户端'+Socket.RemoteHost+'发生错误!';
ErrorCode:=0;
end;
end.
nm使用方法?
nm基本用法命令
nm用来列出目标文件的符号清单。下面是nm命令的格式:
nm[/uploads/title/20240101/659240f52a64a.jpga|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgdebug/uploads/title/20240101/659240f52a64a.jpgsyms][/uploads/title/20240101/659240f52a64a.jpgg|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgextern/uploads/title/20240101/659240f52a64a.jpgonly][/uploads/title/20240101/659240f52a64a.jpgB]
[/uploads/title/20240101/659240f52a64a.jpgC|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgdemangle][/uploads/title/20240101/659240f52a64a.jpgD|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgdynamic][/uploads/title/20240101/659240f52a64a.jpgs|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgprint/uploads/title/20240101/659240f52a64a.jpgarmap]
[/uploads/title/20240101/659240f52a64a.jpgo|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgprint/uploads/title/20240101/659240f52a64a.jpgfile/uploads/title/20240101/659240f52a64a.jpgname][/uploads/title/20240101/659240f52a64a.jpgn|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgnumeric/uploads/title/20240101/659240f52a64a.jpgsort] 输出符号所对应的库的名字,在查找符号在那个库中被定义时比较有用
[/uploads/title/20240101/659240f52a64a.jpgp|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgno/uploads/title/20240101/659240f52a64a.jpgsort][/uploads/title/20240101/659240f52a64a.jpgr|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgreverse/uploads/title/20240101/659240f52a64a.jpgsort][/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgsize/uploads/title/20240101/659240f52a64a.jpgsort]
[/uploads/title/20240101/659240f52a64a.jpgu|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgundefined/uploads/title/20240101/659240f52a64a.jpgonly][/uploads/title/20240101/659240f52a64a.jpgl|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgline/uploads/title/20240101/659240f52a64a.jpgnumbers][/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpghelp]
[/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgversion][/uploads/title/20240101/659240f52a64a.jpgtradix|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgradix=radix]
[/uploads/title/20240101/659240f52a64a.jpgP|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgportability][/uploads/title/20240101/659240f52a64a.jpgfformat|/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgformat=format]
[/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgtarget=bfdname][objfile...]
如果没有为nm命令指出目标文件,则nm假定目标文件是a.out。下面列出该命令的任选项,大部分支持“/uploads/title/20240101/659240f52a64a.jpg”开头的短格式和“/uploads/title/20240101/659240f52a64a.jpg“开头的长格式。
/uploads/title/20240101/659240f52a64a.jpgA、/uploads/title/20240101/659240f52a64a.jpgo或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgprint/uploads/title/20240101/659240f52a64a.jpgfile/uploads/title/20240101/659240f52a64a.jpgname:在找到的各个符号的名字前加上文件名,而不是在此文件的所有符号前只出现文件名一次。
例如nmlibtest.a的输出如下:
CPThread.o:
00000068TMain__8CPThreadPv
00000038TStart__8CPThread
00000014T_._8CPThread
00000000T__8CPThread
00000000?__FRAME_BEGIN__
…………………………………
则nm/uploads/title/20240101/659240f52a64a.jpgA的输出如下:
libtest.a:CPThread.o:00000068TMain__8CPThreadPv
libtest.a:CPThread.o:00000038TStart__8CPThread
libtest.a:CPThread.o:00000014T_._8CPThread
libtest.a:CPThread.o:00000000T__8CPThread
libtest.a:CPThread.o:00000000?__FRAME_BEGIN__
…………………………………………………………..
/uploads/title/20240101/659240f52a64a.jpga或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgdebug/uploads/title/20240101/659240f52a64a.jpgsyms:显示调试符号。
/uploads/title/20240101/659240f52a64a.jpgB:等同于/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgformat=bsd,用来兼容MIPS的nm。
/uploads/title/20240101/659240f52a64a.jpgC或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgdemangle:将低级符号名解码(demangle)成用户级名字。这样可以使得C++函数名具有可读性。
/uploads/title/20240101/659240f52a64a.jpgD或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgdynamic:显示动态符号。该任选项仅对于动态目标(例如特定类型的共享库)有意义。
/uploads/title/20240101/659240f52a64a.jpgfformat:使用format格式输出。format可以选取bsd、sysv或posix,该选项在GNU的nm中有用。默认为bsd。
/uploads/title/20240101/659240f52a64a.jpgg或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgextern/uploads/title/20240101/659240f52a64a.jpgonly:仅显示外部符号。
/uploads/title/20240101/659240f52a64a.jpgn、/uploads/title/20240101/659240f52a64a.jpgv或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgnumeric/uploads/title/20240101/659240f52a64a.jpgsort:按符号对应地址的顺序排序,而非按符号名的字符顺序。
/uploads/title/20240101/659240f52a64a.jpgp或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgno/uploads/title/20240101/659240f52a64a.jpgsort:按目标文件中遇到的符号顺序显示,不排序。
/uploads/title/20240101/659240f52a64a.jpgP或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgportability:使用POSIX.2标准输出格式代替默认的输出格式。等同于使用任选项/uploads/title/20240101/659240f52a64a.jpgfposix。
/uploads/title/20240101/659240f52a64a.jpgs或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgprint/uploads/title/20240101/659240f52a64a.jpgarmap:当列出库中成员的符号时,包含索引。索引的内容包含:哪些模块包含哪些名字的映射。
/uploads/title/20240101/659240f52a64a.jpgr或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgreverse/uploads/title/20240101/659240f52a64a.jpgsort:反转排序的顺序(例如,升序变为降序)。
/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgsize/uploads/title/20240101/659240f52a64a.jpgsort:按大小排列符号顺序。该大小是按照一个符号的值与它下一个符号的值进行计算的。
/uploads/title/20240101/659240f52a64a.jpgtradix或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgradix=radix:使用radix进制显示符号值。radix只能为“d”表示十进制、“o”表示八进制或“x”表示十六进制。
/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgtarget=bfdname:指定一个目标代码的格式,而非使用系统的默认格式。
/uploads/title/20240101/659240f52a64a.jpgu或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgundefined/uploads/title/20240101/659240f52a64a.jpgonly:仅显示没有定义的符号(那些外部符号)。
/uploads/title/20240101/659240f52a64a.jpgl或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgline/uploads/title/20240101/659240f52a64a.jpgnumbers:对每个符号,使用调试信息来试图找到文件名和行号。对于已定义的符号,查找符号地址的行号。对于未定义符号,查找指向符号
重定位入口的行号。如果可以找到行号信息,显示在符号信息之后。
/uploads/title/20240101/659240f52a64a.jpgV或/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpgversion:显示nm的版本号。
/uploads/title/20240101/659240f52a64a.jpg/uploads/title/20240101/659240f52a64a.jpghelp:显示nm的任选项。
ar cs libmy.a//创建一个库
ar rs libmy.a 1.o//增加一个模块
ar t libmy.a//显示库里的模块
ar d libmy.a 1.o//删除一个模块
nm命令的输出:
关于符号的类型,这里我们再多讨论一下。符号的类型是以一个字母的形式显示的,小写字母表示这个符号是本地(local)的,而大写字母则表示这个
符号是 全局的(global,externel)。
一般来说,类型有一下几种:T、D、B、U、W。各自的含义如下:
T表示在代码段中定义的一般变量符号;
D表示是初始化过的数据段;
B表示初始化的数据段;
U表示没有定义的,在这个库里面使用了,但是在其他库中定义的符号;
W,weak的缩写,表示如果其他函数库中也有对这个符号的定义,则其他符号的定义可以覆盖这个定义。
使用多线程的几种方式示例详解?
多线程使用的主要的几种形式:
1)使用Thread类创建一个新线程
static void Main(string[] args){ Thread thread = new Thread(delegate(){ for (int i = 0; i <= 10; i++){ Console.WriteLine(Thread.CurrentThread.Name + ":" + i); Thread.Sleep(100); } }); thread.Name = "t1 thread"; thread.Start(); Console.WriteLine("TO DO SOMETHING..."); Console.ReadKey(true);}
2)使用async与await关键字配合使用
static void Main(string[] args){ Console.WriteLine("Main method start..."); Foo(); Console.WriteLine("TO DO SOMETHING..."); Console.WriteLine("Main method end..."); Console.ReadKey(true);} async static void Foo(){ Console.WriteLine("Foo method start."); await Task.Delay(2000); Console.WriteLine("Foo method end.");}
3)使用委托内置的实例方法BeginInvoke实现异步编程
static void Main(string[] args){ Func
唱起歌儿快乐多英文版?
DoReMi 唱起歌儿快乐多。英文版歌词:
let's start at the very beginning,a very good place to start.
when you read you begin with a/uploads/title/20240101/659240f52a64a.jpgb/uploads/title/20240101/659240f52a64a.jpgc,when you sing you begin with do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi.
do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi, do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi,the first three notes just happen to be.
do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi, do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi,do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi/uploads/title/20240101/659240f52a64a.jpgfa/uploads/title/20240101/659240f52a64a.jpgso/uploads/title/20240101/659240f52a64a.jpgla/uploads/title/20240101/659240f52a64a.jpgti,let's see if i can make it easy.
doe, a deer, a female deer,ray, a drop of golden sun.
me, a name i call myself,far, a long, long way to run.
sew, a needle pulling thread,la, a note to follow sew.
tea, a drink with jam and bread,that will bring us back to do (oh/uploads/title/20240101/659240f52a64a.jpgoh/uploads/title/20240101/659240f52a64a.jpgoh)ha.
do/uploads/title/20240101/659240f52a64a.jpgre/uploads/title/20240101/659240f52a64a.jpgmi/uploads/title/20240101/659240f52a64a.jpgfa/uploads/title/20240101/659240f52a64a.jpgso/uploads/title/20240101/659240f52a64a.jpgla/uploads/title/20240101/659240f52a64a.jpgti/uploads/title/20240101/659240f52a64a.jpgdo.
mfc添加主副线程源码?
这个问题不太明确,可能需要具体的情境或者细节上的说明。如果是关于 MFC 编程中如何添加主线程和副线程的源码,那么可以开启一个主线程,并且在主线程中使用 AfxBeginThread() 函数创建一个新的副线程,并且在副线程中编写相应的代码。具体的源码需要结合具体的需求和情境进行编写,具体步骤和细节可以查看 MFC 编程相关文档或者教程。
本站涵盖的内容、图片等数据系网络收集,部分未能与原作者取得联系。若涉及版权问题,请联系ynstorm@foxmail.com进行删除!