Symbian 线程编程 | 实例

转自:http://blog.csdn.net/arthersophy/archive/2010/04/20/5506639.aspx

线程编程在symbian os中不被鼓励使用,想来原因大家都已经知道了(线程上下文切换比活动对象开销大 等),但是对于一些特殊的需求及应用,还是需要多线程编程的,比如多媒体编程。在播放流媒体或者声音的时候,必须保证任务的连续性。

具体理论不明白的地方,请参看:Symbian c/s 机制分析

自己写了个例子,代码如下。

RThreadClien.h

public RThreadClient : public RSessionBase
    {
public:
    IMPORT_C RThreadClient();
    IMPORT_C ~RThreadClient();

public:
    IMPORT_C TInt ConnectToServer(const TDesC& aName);
    IMPORT_C TInt SendReceive(TInt aFunction) const;
    IMPORT_C TInt SendReceive(TInt aFunction,const TIpcArgs& aArgs) const;
    IMPORT_C void SendReceive(TInt aFunction,const TIpcArgs& aArgs,TRequestStatus& aStatus) const;


private:
    TVersion Version();
    void DoConnectL(const TDesC& aName);
    };

RThreadClient.cpp

#include "ThreadClient.h"
#include "ThreadServer.h"

const TInt KNumConnectRetries        = 5;
const TInt KMaxNumberOfMessageSlots    = 255;

EXPORT_C RThreadClient::RThreadClient()
    {
    }

EXPORT_C RThreadClient::~RThreadClient()
     {
    }

EXPORT_C TInt RThreadClient::ConnectToServer(const TDesC& aName)  //连接到server
    {
    TInt ret = KErrNone;
    if (Handle() == 0)   // 保证一个client有一个handle.
        {
        TRAPD(ret, DoConnectL(aName));
        if (ret != KErrNone)
            {
            Close();
            }
        }
    return ret;
    }


TVersion RThreadClient::Version()
    {
    TVersion v(1,1,1);
    return v;
    }

static void ThreadFunL(TAny* aData)
    {
    CActiveScheduler* scheduler = new (ELeave) CActiveScheduler(); //安装活动调度器
    CleanupStack::PushL(scheduler);
    CActiveScheduler::Install(scheduler);

    CThreadServer* server = CThreadServer::NewL(); //new a custom server
    CleanupStack::PushL(server);
    const TDesC& name = *static_cast<const TDesC*>(aData);
    server->StartL(name);
    RThread::Rendezvous(KErrNone);

    CActiveScheduler::Start();  //启动活动调度器

    // Delete active scheduler
    CleanupStack::PopAndDestroy(2, scheduler);    //scheduler, engine
    }

static TInt ThreadFun(TAny* aData)
    {
    CTrapCleanup* cleanup = CTrapCleanup::New(); //手动安装清楚栈。
    TInt error = KErrNone;
    if(cleanup)
        {
        TRAP(error, ThreadFunL(aData));
        
        }
    delete cleanup;

    return error;
    }

void DoLaunchThreadL(const TDesC& aThreadName, TBool aUseSemaphore)
    {
    TRequestStatus started, died;

    RThread thread;
    User::LeaveIfError(thread.Create(aThreadName, ThreadFun, 8192, NULL, const_cast<TDesC*>(&aThreadName)));//创建一个用户线程。

    thread.Logon(died); // 向线程注册一下,你能够监听到线程取消或者死忘。
        
    if (aUseSemaphore)
        {
        thread.Rendezvous(started); // 线程同步一种方式。不是数据交换。请求得到服务线程调用 Rendezvous(TInt) 的通知
        if (started != KRequestPending)
            {
            thread.Kill(0); // abort startup
            return;
            }
        }

    // Logon OK - Start the epocExe
    thread.Resume();   //启动线程。

    if (aUseSemaphore)
        {
        User::WaitForRequest(started, died); // wait for start or death
        if (started==KRequestPending)
            {
            thread.RendezvousCancel(started);
            thread.Close();
            User::LeaveIfError(died.Int());
            }
        }

    thread.LogonCancel(died); //取消注册
    thread.Close(); 
    User::WaitForRequest(died);    
    }

void RThreadClient::DoConnectL(const TDesC& aName)
    {
    TInt err = KErrNone;
    TInt count = 0;
    TBool serverStarted = EFalse;
    FOREVER
        {
        err = CreateSession(aName, Version(), KMaxNumberOfMessageSlots);  // 创建session,session代表一个client和

// server的链接,也就是说,如果Client端调用了RSessionBase::CreateSession(),那么Server端的 NewSessionL就会被调用。猜//测下Server的实现如下:当Client端调用了RSessionBase::CreateSession (),内核找到相应的Server,然后Server线程的AS会//check这个Client在Server端有没有对应的Session,如果没有就调 用NewSessionL来创建一个Session。Client和Server后续的数据// 操作都通过这个Session来完成。 ×区别于自定义的CThreadServer ×
        if (err == KErrNone) //已经存在了
            {
            break;
            }
        if ((err != KErrNotFound) || (count++ == KNumConnectRetries))
            {
            User::LeaveIfError(err);
            }
        if (!serverStarted)
            {
            DoLaunchThreadL(aName, ETrue);
            serverStarted = ETrue;
            }
        }
    }

EXPORT_C TInt RThreadClient::SendReceive(TInt aFunction, const TIpcArgs& aArgs) const
    {
    return RSessionBase::SendReceive(aFunction, aArgs);
    }

EXPORT_C TInt RThreadClient::SendReceive(TInt aFunction) const
    {
    return RSessionBase::SendReceive(aFunction);
    }

EXPORT_C void RThreadClient::SendReceive(TInt aFunction,const TIpcArgs& aArgs,TRequestStatus& aStatus) const
    {
    RSessionBase::SendReceive(aFunction, aArgs, aStatus);
    }

CThreadServer.h


#ifndef __THREADSERVER_H__
#define __THREADSERVER_H__

#include <e32base.h>

enum TRequestType
    {
    EDoStart,
    ECancel,
    ECustomCommand,
    };

// CServer2    是一个AO,从客户线程接受请求,然后把这些请求分发到相应的服务器端的客户session。它可以利用客户线程请求来创

//建服务器端的客户线程。 
public CThreadServer : public CServer2
    {
public:
    static CThreadServer* NewL();
    ~CThreadServer();

    void DisconectServer();

private:
    // From CServer2
    virtual CSession2* NewSessionL(const TVersion& aVersion,
            const RMessage2 &aMessage) const;


private:
    CThreadServer();
    void ConstructL();
    TInt SessionCount();

private:
    };


#endif  // __THREADSERVER_H__

CThreadServer.cpp 
#include <BAUTILS.H>
#include <eikenv.h>
#include <w32std.h>
#include "ThreadServer.h"
#include "ThreadSession.h"



CThreadServer* CThreadServer::NewL()
    {
    CThreadServer* self = new (ELeave) CThreadServer();
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
    }

CThreadServer::CThreadServer() : CServer2(CActive::EPriorityStandard)
    {
    }

CThreadServer::~CThreadServer()
    {
    }

void CThreadServer::ConstructL()
    {
    }


CSession2* CThreadServer::NewSessionL(const TVersion& aVersion, const RMessage2&) const
    {
    const TVersion v(1, 1, 1);
    if (!User::QueryVersionSupported(v, aVersion))
        {
        User::Leave(KErrNotSupported);    
        }
    return CThreadSession::NewL();
    }

void CThreadServer::DisconectServer()
    {
    if (SessionCount() == 0)
        {
        CActiveScheduler::Stop();
        }
    }

TInt CThreadServer::SessionCount()
    {
    iSessionIter.SetToFirst();
    TInt i = 0;
    while (iSessionIter++)
        {
        ++i;
        }
    return i;
    }
//end of file

CThreadSessio.h

#ifndef PointrProtectSESSION_H_
#define PointrProtectSESSION_H_

#include <e32base.h>
#include <f32file.h>
// CSession2   服务器端的客户Session,   充当  Client和Server  的通信信道,一个Client线程能和一个Server并发多个线程。 
class CThreadServer;    
public CThreadSession : public CSession2
    {
public:
    static CThreadSession* NewL();
    ~CThreadSession();

public:
    // From CSession2
    virtual void ServiceL(const RMessage2& aMessage);
    virtual void Disconnect(const RMessage2& aMessage);

private:
    CThreadSession();
    void ConstructL();

private:
    void DoServiceL(const RMessage2& aMessage);


private:
    };

#endif /*PointrProtectSESSION_H_*/

CThreadSession.cpp

#include "ThreadSession.h"
#include "ThreadServer.h"
#include "BaseWorker.h"


CThreadSession* CThreadSession::NewL()
    {
    CThreadSession* self = new (ELeave) CThreadSession();
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
    }

CThreadSession::CThreadSession() 
    {
    }

CThreadSession::~CThreadSession()
    {
    }

void CThreadSession::ConstructL()
    {
    }

void CThreadSession::ServiceL(const RMessage2& aMessage)
    {
    TRAPD(err, DoServiceL(aMessage));
    if (err != KErrNone)
        {
        aMessage.Complete(err);
        }
    }


void CThreadSession::DoServiceL(const RMessage2& aMessage)
    {
    switch (aMessage.Function())
        {
        case EDoStart:
            {
        
            }
            break;
        case ECancel:
            {
         
            }
            break;
        default:
            {
          
            }
            break;
        }
    }

void CThreadSession::Disconnect(const RMessage2& aMessage)
    {
    CThreadServer* server = const_cast<CThreadServer*>(static_cast<const CThreadServer* >(Server()));
    CSession2::Disconnect(aMessage);
    server->DisconectServer();
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值