Basic Of Multi-Threads

本文介绍Symbian系统中多线程编程的基础知识,包括RHandleBase类的使用方法,RThread类的主要功能如Create(), Resume(), Kill()等,以及RSemaphore类的基本操作如Wait(), Signal(), Count()等。
1] RHandleBase 类

作为多线程,首先要考虑到的是 RThread 类。RThread 类从 RHandleBase 类继承,所以它首先是一个对象的句柄(a handle of an object),包括了 Close(), Duplicate(), FullName(), Handle(), HandleInfo(), Name(), RHandleBase(), SetHandle(), SetHandleNC() 方法。这个类是一个抽象类,没有自己的实例,通常都是作为其他类的基类使用,例如 RSemaphore, RThread, RProcess, RCriticalSection 等。RTimer 类是从RHandleBase 继承的一个类,可以通过这个类,来说明一些 RHandleBase 的一些问题 。 以下是代码。

#include <e32base.h>
#include <e32cons.h>

// 定义本地数据
LOCAL_D CConsoleBase* console;
LOCAL_C void NewCsoLC();
LOCAL_D TInt err;

//全局函数,被 E32 调用的主函数,
GLDEF_C TInt E32Main()
{
__UHEAP_MARK;
CTrapCleanup* cup=CTrapCleanup::New();
TRAP(err,NewCsoLC());
delete cup;
__UHEAP_MARKEND;
return 0;
}

LOCAL_C void NewCsoLC()
{
__UHEAP_MARK;
_LIT(TITLE,"RHandleBase Demo");
TSize Ts=TSize();
Ts.SetSize(-1,-1);
console=Console::NewL(TITLE,Ts);
CleanupStack::PushL(console);


RTimer RTM;
//创建一个与系统计时器相关联的句柄
RTM.CreateLocal();

//RTM.Close();
//RTM.CreateLocal();


// 获得与当前句柄相关联对象的 handle-number
console->Printf(_L("HandleNum:"));
console->Printf(_L("%d"),RTM.Handle());
console->Printf(_L(" "));

// 设置与当前句柄相关联对象的 handle-number
// 这个值似乎不能乱设,否则将导致系统异常,具体细节不甚清楚
//RTM.SetHandle(180000000);
//RTM.SetHandleNC(18000000000);
//console->Printf(_L("HandleNum:"));
//console->Printf(_L("%d"),RTM.Handle());
//console->Printf(_L(" "));


// 获得句柄全名
console->Printf(_L("FullName:"));
console->Printf(RTM.FullName());
console->Printf(_L(" "));

// 获得句名称
console->Printf(_L("Name:"));
console->Printf(RTM.Name());
console->Printf(_L(" "));

// HandleInfo() 方法需要传入一个 THandleInfo 型的指针
THandleInfo* Hif;
RTM.HandleInfo(Hif);
// 通过这个 Hif 指针可以获取和设置与句柄相关的系统对象的信息。
console->Printf(_L("iNumOpenInProcess:%d "),Hif->iNumOpenInProcess);
console->Printf(_L("iNumOpenInThread:%d "),Hif->iNumOpenInThread);
console->Printf(_L("iNumProcesses:%d "),Hif->iNumProcesses);
console->Printf(_L("iNumThreads:%d "),Hif->iNumThreads);

Hif->iNumOpenInProcess=8;
Hif->iNumOpenInThread=9;
Hif->iNumProcesses=90;
Hif->iNumThreads=4;

console->Printf(_L("iNumOpenInProcess:%d "),Hif->iNumOpenInProcess);
console->Printf(_L("iNumOpenInThread:%d "),Hif->iNumOpenInThread);
console->Printf(_L("iNumProcesses:%d "),Hif->iNumProcesses);
console->Printf(_L("iNumThreads:%d "),Hif->iNumThreads);

//关闭句柄
/*
这个操作对与句柄相关的内核对象也有一定作用。
与句柄相关联的对象似乎是一个引用计数对象,
当外部不再有对该内核对象打开的引用时,Close()方法可以销毁这个内核对象
*/
RTM.Close();
console->Printf(_L("Press to end "));

console->Getch();
CleanupStack::PopAndDestroy();
__UHEAP_MARKEND;
}

[2] RThread 类

在这个类中,需要了解他主要的几个方法。

1.Create()方法:这个方法有四个版本的重载函数,但是基本的参数也就这些:

参 数描 述
const TDesC& aName线程的名称
TThreadFunction aFunction一个指向函数的指针,当线程被恢复时调用该函数,也就是线程最初预定运行的函数。
TInt aStackSize新线程的 Stack 大小,它不可以为负值,否则函数将发生 USER 109 panic
TAny* aPtr一个指向数据的指针,这些数据是线程函数运行所需要的,如果线程函数不需要参数,则可以把该指针置为NULL
TInt aHeapMinSize 新线程 heap 的最小值, 这个值必须不小于在 e32std.h 中定义的 KMinHeapSize,否则函数将发生 USER 110 panic
TInt aHeapMaxSize新线程的 heap 的最大值, 它必须不小于 aHeapMinSize,否则函数将个发生 USER 111 panic
TOwnerType aType它是一个枚举型变量,指明要创建的线程是属于进程还是线程,如果这个值没有被指定,那么将默认 EOwnerProcess,也就是说,新的线程是属于进程的。
RProcess* aProcess指明当前线程所属的进程
RLibrary* aLibrary指明线程函数所在的 DLL

2.Resume() 方法:这个方法使创建好的线程处于执行状态。刚刚创建好的线程是处在暂停状态的,Resume() 方法使线程从暂停态转到执行态。

3.Kill() 方法:以指定的原因代码退出指定线程;它与 User::Exit() 的功能类似。

[3] RSemaphore

Semaphore 应该是信号量的意思,这个应该是《操作系统》里的知识吧。信号量(semaphore)是一个内核对象,RSemaphore类提供了对 semaphore的句柄引用。既然它是一个资源类,那么他的使用和操作其他资源类是类似的,在使用前要创建、使用完成后要关闭。

1.Wait() 方法:使信号量减 1。

2.Signal() 方法:使信号量增加 1,如果带参数,则使增加参数所指定的量。

3.Count() 方法:返回当前信号量的值;

以下是两个线程同时使用 两个 TInt 型 :num 和 Tnum 的程序,在这里下载 VC++6 工程文件

#include <e32base.h>
#include <e32cons.h>
#include <E32math.h>

// 定义本地数据
LOCAL_D CConsoleBase* console;
LOCAL_C void ThreadL();
LOCAL_C void NewCsoLC();

LOCAL_C TReal GetRandom();
LOCAL_D TInt err;

const TUint KDefaultHeapSize=0x10000;
//信号量句柄
RSemaphore semaphore;
TInt num;

LOCAL_D RThread T_1,T_2;
LOCAL_D TInt Tnum;

//全局函数,被 E32 调用的主函数,
GLDEF_C TInt E32Main()
{
__UHEAP_MARK;
CTrapCleanup* cup=CTrapCleanup::New();
TRAP(err,NewCsoLC());
delete cup;
__UHEAP_MARKEND;
return 0;
}

LOCAL_C void NewCsoLC()
{
__UHEAP_MARK;
_LIT(TITLE,"RThread Demo");
TSize Ts=TSize();
Ts.SetSize(-1,-1);
console=Console::NewL(TITLE,Ts);
CleanupStack::PushL(console);

console->Printf(_L("Press [C] or [D] "));

TInt i=0;
TKeyCode key;
while(i<1000)
{
key=console->Getch();
//按 Esc 键 退出
__ASSERT_ALWAYS(key!=27,User::Panic(_L("End Thread"),key));
console->Printf(_L("[%d:%c] "),key,key);

// 按 C 键 清除屏幕
if (key==99)
{
console->SetTitle(_L("ClearScreen"));
console->ClearScreen();
}

//press 1 User::After 测试
if (key==49)
{
console->SetTitle(_L("User::After Test"));
for(TInt myi=0;myi<=100;myi++)
{
User::After(10000*(100-myi));
console->Printf(_L("showText:%d "),myi);
}
}

//press 2 User::At 测试
if (key==50)
{
console->SetTitle(_L("User::At Test"));
TTime ttm;
ttm.HomeTime();

TDateTime dtm;
dtm=ttm.DateTime();
console->Printf(_L("%d-%d-%d %d:%d:%d.%d "),dtm.Year,dtm.Month(),dtm.Day(),dtm.Hour(),dtm.Minute(),dtm.Second(),dtm.MicroSecond());
TTimeIntervalSeconds itv=3;
ttm+=(itv);
dtm=ttm.DateTime();
console->Printf(_L("%d-%d-%d %d:%d:%d.%d "),dtm.Year,dtm.Month(),dtm.Day(),dtm.Hour(),dtm.Minute(),dtm.Second(),dtm.MicroSecond());

User::At(ttm);
console->Printf(_L("User::At Test "));
}
// 按 B
if (key==98)
{

TInt64 seed = User::TickCount();
//console->Printf(_L("seed=%d "),seed);
//while(true)
TReal64 a=9;
Math::Pow(a,TReal(2),TReal(32));

console->Printf(_L("%f "),a);

console->Printf(_L("%f "),TReal(Math::Random())/a);

/*
for(TInt ib=0;ib<=10;ib++)
{
User::Beep(1000000,1000000);
}
*/
}
// 按 D
if (key==100)
{

TRAPD(err,ThreadL());
}
}

CleanupStack::PopAndDestroy();
__UHEAP_MARKEND;
}

TInt ThreadFunction(TAny* aAny)
{

TInt *increment = reinterpret_cast<TInt*>(aAny);
for(TInt i=0;i<100;i++)
{
//semaphore.Wait();
Tnum=*increment;
num =100+TInt((*increment)*GetRandom());
User::After(TInt(500000*GetRandom()));

if(i>50)
{
T_1.Kill(0);
semaphore.Signal();
}
if(i>70)
{
T_2.Kill(0);
semaphore.Signal();
}

}
//使信号量的值增加
semaphore.Signal();
Tnum=*increment+10;
return 0;

}

 

LOCAL_C void ThreadL()
{

num = 100;

TInt inc1 = 10, inc2 = -10;

TInt err = T_1.Create(_L("T_1"),ThreadFunction,KDefaultStackSize,KDefaultHeapSize,KDefaultHeapSize,&inc1);
CleanupClosePushL(T_1);
User::LeaveIfError(err);

err = T_2.Create(_L("T_2"),ThreadFunction,KDefaultStackSize,KDefaultHeapSize,KDefaultHeapSize,&inc2);
CleanupClosePushL(T_2);
User::LeaveIfError(err);

//创建一个信号量并初始化
semaphore.CreateLocal(0);


T_1.Resume();
console->Printf(T_1.FullName());
console->Printf(_L(" "));

//
User::After(100000);

T_2.Resume();
console->Printf(T_2.FullName());
console->Printf(_L(" "));


while(semaphore.Count()<2)
{
console->Printf(_L("[%d:%d] "),Tnum,num);
User::After(10);

}

console->Printf(_L("[%d:%d] "),Tnum,num);

T_1.Kill(0);
T_2.Kill(0);

T_1.Close();

// 当两个进程都结束了,那么
// 弹出栈顶的两个元素
CleanupStack::PopAndDestroy(2);

console->Printf(_L("Thread Test: "));

}

// 获得一个O-1的随机数
LOCAL_C TReal GetRandom()
{
TReal64 a=0;
Math::Pow(a,TReal(2),TReal(32));
a=TReal(Math::Random())/a;
return a;

}

 
内容概要:文章以“智能网页数据标注工具”为例,深入探讨了谷歌浏览器扩展在毕业设计中的实战应用。通过开发具备实体识别、情感分类等功能的浏览器扩展,学生能够融合前端开发、自然语言处理(NLP)、本地存储与模型推理等技术,实现高效的网页数据标注系统。文中详细解析了扩展的技术架构,涵盖Manifest V3配置、内容脚本与Service Worker协作、TensorFlow.js模型在浏览器端的轻量化部署与推理流程,并提供了核心代码实现,包括文本选择、标注工具栏动态生成、高亮显示及模型预测功能。同时展望了多模态标注、主动学习与边缘计算协同等未来发展方向。; 适合人群:具备前端开发基础、熟悉JavaScript和浏览器机制,有一定AI模型应用经验的计算机相关专业本科生或研究生,尤其适合将浏览器扩展与人工智能结合进行毕业设计的学生。; 使用场景及目标:①掌握浏览器扩展开发全流程,理解内容脚本、Service Worker与弹出页的通信机制;②实现在浏览器端运行轻量级AI模型(如NER、情感分析)的技术方案;③构建可用于真实场景的数据标注工具,提升标注效率并探索主动学习、协同标注等智能化功能。; 阅读建议:建议结合代码实例搭建开发环境,逐步实现标注功能并集成本地模型推理。重点关注模型轻量化、内存管理与DOM操作的稳定性,在实践中理解浏览器扩展的安全机制与性能优化策略。
基于Gin+GORM+Casbin+Vue.js的权限管理系统是一个采用前后端分离架构的企业级权限管理解决方案,专为软件工程和计算机科学专业的毕业设计项目开发。该系统基于Go语言构建后端服务,结合Vue.js前端框架,实现了完整的权限控制和管理功能,适用于各类需要精细化权限管理的应用场景。 系统后端采用Gin作为Web框架,提供高性能的HTTP服务;使用GORM作为ORM框架,简化数据库操作;集成Casbin实现灵活的权限控制模型。前端基于vue-element-admin模板开发,提供现代化的用户界面和交互体验。系统采用分层架构和模块化设计,确保代码的可维护性和可扩展性。 主要功能包括用户管理、角色管理、权限管理、菜单管理、操作日志等核心模块。用户管理模块支持用户信息的增删改查和状态管理;角色管理模块允许定义不同角色并分配相应权限;权限管理模块基于Casbin实现细粒度的访问控制;菜单管理模块动态生成前端导航菜单;操作日志模块记录系统关键操作,便于审计和追踪。 技术栈方面,后端使用Go语言开发,结合Gin、GORM、Casbin等成熟框架;前端使用Vue.js、Element UI等现代前端技术;数据库支持MySQL、PostgreSQL等主流关系型数据库;采用RESTful API设计规范,确保前后端通信的标准化。系统还应用了单例模式、工厂模式、依赖注入等设计模式,提升代码质量和可测试性。 该权限管理系统适用于企业管理系统、内部办公平台、多租户SaaS应用等需要复杂权限控制的场景。作为毕业设计项目,它提供了完整的源码和论文文档,帮助学生深入理解前后端分离架构、权限控制原理、现代Web开发技术等关键知识点。系统设计规范,代码结构清晰,注释完整,非常适合作为计算机相关专业的毕业设计参考或实际项目开发的基础框架。 资源包含完整的系统源码、数据库设计文档、部署说明和毕
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值