×
Namespaces

Variants
Actions
Revision as of 11:29, 24 June 2011 by hamishwillee (Talk | contribs)

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

From Nokia Developer Wiki
Jump to: navigation, search


Template:KBCS

Article Metadata
Tested with
Devices(s): Nokia N95
Compatibility
Platform(s): S60 3rd Edition, MR
S60 3rd Edition (initial release)
Platform Security
Capabilities: )
Article
Keywords: CActiveSchedulerWait, CActive, TRequestStatus
Created: tepaa (10 Jun 2008)
Last edited: hamishwillee (24 Jun 2011)

Overview

This code snippet shows how to modify a synchronous method to behave like an asynchronous method.

There are two different methods:

  • void LongRunningTaskL(TInt& aResult) is a synchronous method that acts like an asynchronous one but returns when the task has been completed.
  • void LongRunningTaskL(MMySynchronousTaskDone* aObserver) is a synchronous method that acts like an asynchronous method. Note that the method returns right after it has been started and notifies of 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 acts like an asynchronous one
// but returns when task completed.
void LongRunningTaskL(TInt& aResult);
 
// Synchronous method that acts like an asynchronous one
// note that the method returns right after it has been started
// and notifies of 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);
iSchedulerWait = new (ELeave) CActiveSchedulerWait();
}
 
CMySynchronousClass::~CMySynchronousClass()
{
Cancel();
delete iSchedulerWait;
}
 
// 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 the 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: Here is a synchronous method call.
// Try to split call in small parts.
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

The synchronous method acts like an asynchronous one.

See also

CS000982 - Using CActiveSchedulerWait

Change_asynchronous_method_into_synchronous

79 page views in the last 30 days.