×
Namespaces

Variants
Actions
Revision as of 10:50, 27 May 2008 by tepaa (Talk | contribs)

Archived:Change a synchronous Symbian C++ method to act like an asynchronous one

From Nokia Developer Wiki
Jump to: navigation, search


ID Creation date May 27, 2008
Platform S60 3rd Edition, MR Tested on devices Nokia N95
Category Symbian C++ Subcategory Code Examples


Keywords (APIs, classes, methods, functions): CActiveSchedulerWait, CActive, TRequestStatus

Overview

This code snippet shows how to change synchronous method act like asynchronous.

There is two different method:

  • void LongRunningTaskL(TInt& aResult) is synchronous method that act like asynchronous but returns when task done
  • void LongRunningTaskL(MMySynchronousTaskDone* aObserver) is synchronous method that act like asynchronous. Note that method returns right after it has been started and notifies task completion via MMySynchronousTaskDone

MMP file

The following capabilities and libraries are required:

CAPABILITY    None
LIBRARY euser.lib

Header

#include <e32base.h>
 
class MMySynchronousTaskDone
{
public:
virtual void TaskDone(TInt aRet) = 0;
};
 
class CMySynchronousClass : public CActive
{
enum EState
{
EIdle = 0,
EStarted,
ERunningTask1,
ERunningTask2,
ERunningTask3,
EEnd
};
 
public:
static CMySynchronousClass* NewL();
virtual ~CMySynchronousClass();
 
public:
// Synchronous method that act like asynchronous
// but returns when task done.
void LongRunningTaskL(TInt& aResult);
 
// Synchronous method that act like asynchronous
// note that method returns right after it has been started
// and notifies task completion via MMySynchronousTaskDone
void LongRunningTaskL(MMySynchronousTaskDone* aObserver);
 
private: // From CActive
void RunL();
TInt RunError(TInt aError);
void DoCancel();
 
private:
CMySynchronousClass();
void ConstructL();
void GiveTimeToOthers();
void DoLongRunningTask();
 
private:
EState iRunningState;
CActiveSchedulerWait iSchedulerWait;
TInt iSomeLongRunningTask;
MMySynchronousTaskDone* iObserver;
};

Source

CMySynchronousClass* CMySynchronousClass::NewL()
{
CMySynchronousClass* self = new (ELeave) CMySynchronousClass();
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop();
return self;
}
 
CMySynchronousClass::CMySynchronousClass():CActive(EPriorityStandard)
{
}
 
void CMySynchronousClass::ConstructL()
{
CActiveScheduler::Add(this);
}
 
CMySynchronousClass::~CMySynchronousClass()
{
Cancel();
}
 
// This method returns after synchronous task completion
void CMySynchronousClass::LongRunningTaskL(TInt& aResult)
{
if (iRunningState == EIdle)
{
iSomeLongRunningTask = 0;
iRunningState = EStarted;
 
GiveTimeToOthers();
iSchedulerWait.Start();
 
// Continues here after CActiveSchedulerWait::AsyncComplete() is called
if (iStatus.Int() != KErrNone)
{
User::Leave(iStatus.Int());
}
aResult = iSomeLongRunningTask;
}
else
{
User::Leave(KErrNotReady);
}
}
 
// This method returns right after synchronous task is started
void CMySynchronousClass::LongRunningTaskL(MMySynchronousTaskDone* aObserver)
{
if (iRunningState == EIdle)
{
iObserver = aObserver;
iSomeLongRunningTask = 0;
iRunningState = EStarted;
GiveTimeToOthers();
}
else
{
User::Leave(KErrNotReady);
}
 
}
 
void CMySynchronousClass::DoLongRunningTask()
{
// TODO: You must execute synchronous method in small steps and
// call GiveTimeToOthers() in between steps
iSomeLongRunningTask++;
}
 
void CMySynchronousClass::GiveTimeToOthers()
{
TRequestStatus* status = &iStatus;
User::RequestComplete( status, KErrNone );
SetActive();
}
 
void CMySynchronousClass::RunL()
{
switch (iRunningState)
{
case EIdle:
{
break;
}
case EStarted:
{
iRunningState = ERunningTask1;
// TODO: Call synchronous method
DoLongRunningTask();
 
GiveTimeToOthers();
break;
}
case ERunningTask1:
{
iRunningState = ERunningTask2;
// TODO: Call synchronous method
DoLongRunningTask();
 
GiveTimeToOthers();
break;
}
case ERunningTask2:
{
iRunningState = ERunningTask3;
// TODO: Call synchronous method
DoLongRunningTask();
 
GiveTimeToOthers();
break;
}
case ERunningTask3:
{
iRunningState = EEnd;
// TODO: Do some end processing if needed
 
GiveTimeToOthers();
break;
}
case EEnd:
{
// Done
iRunningState = EIdle;
if (iObserver)
{
iObserver->TaskDone(iSomeLongRunningTask);
}
if (iSchedulerWait.IsStarted())
{
iSchedulerWait.AsyncStop();
}
break;
}
default:
{
if (iSchedulerWait.IsStarted())
{
iSchedulerWait.AsyncStop();
}
break;
}
};
}
 
TInt CMySynchronousClass::RunError(TInt aError)
{
if (iObserver)
{
iObserver->TaskDone(aError);
}
return KErrNone;
}
 
void CMySynchronousClass::DoCancel()
{
if (iObserver)
{
iObserver->TaskDone(KErrCancel);
}
if (iSchedulerWait.IsStarted())
{
iSchedulerWait.AsyncStop();
}
}

Postconditions

Synchronous methods act a like asynchronous.

See also

Using_CActiveSchedulerWait

Change_asynchronous_method_into_synchronous

72 page views in the last 30 days.