Archived:Change a synchronous Symbian C++ method to act like an asynchronous one
(New page: __NOTOC__ __NOEDITSECTION__ {|style="background:#eceff2" width="660px" border="1" cellpadding="5" cellspacing="0" |- |'''ID''' || |'''Creation date''' || May 27, 2008 |- |'''Platform''' ...) |
|||
| Line 263: | Line 263: | ||
==See also== | ==See also== | ||
[[Using_CActiveSchedulerWait]] | [[Using_CActiveSchedulerWait]] | ||
| + | |||
[[Change_asynchronous_method_into_synchronous]] | [[Change_asynchronous_method_into_synchronous]] | ||
[[Category:Symbian C++]][[Category:Code Examples]] | [[Category:Symbian C++]][[Category:Code Examples]] | ||
Revision as of 10:48, 27 May 2008
| 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()
{
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.

