Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » Developing U++ » U++ Developers corner » BackgroundTask
BackgroundTask [message #31240] Wed, 16 February 2011 13:52 Go to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

As discussed in the thread about MT in theide, there is sometimes need to run some lengthy task in background, while the rest of Application stays responsive.

Ideal solution should use Thread in MT mode and ProcessEvents() in single threaded environment to achieve maximum effectiveness. Here is my first attempt to create such class:
bool ProcessForeground(){
#ifdef _MULTITHREADED
	DUMP(Thread::IsShutdownThreads());
	return !Thread::IsShutdownThreads();
#else
	Ctrl::ProcessEvents();
	return true; //is it possible to detect application is being closed?
#endif
}

class BackgroundTask{
	typedef BackgroundTask CLASSNAME;
	#ifdef _MULTITHREADED
	Thread t;
	#endif
	bool running;
	void Watch(Callback task)         {running=true; task(); running=false;}
public:
	void Start(Callback task);
	bool IsRunning()                  {return running;}
	BackgroundTask():running(false){}
	BackgroundTask(Callback task)     {Start(task);}
};

void BackgroundTask::Watch(Callback task){
	running=true;
	task();
	running=false;
}

void BackgroundTask::Start(Callback task){
	#ifdef _MULTITHREADED
	t.Run(THISBACK1(Watch,task));
	#else
	PostCallback(THISBACK1(Watch,task));
	#endif
}

There is few requirements on the task and application that runs it. Task must call ProcessForeground() periodically, often enough to keep the UI responsive. If ProcessForeground() returns false, the task must finish as soon as possible. In MT mode the application must call Thread::ShutdownThreads(), so that any running tasks know that it is time to terminate itself.

In attachment there is a full code of a testing app. Known bugs: In ST mode you must close the window twice (press Alt+F4 or cross button twice), to make it really close. Probably easy to fix. In MT, calling ShutdownThreads assumes that there are no threads expected to run even after the Background tasks are terminated. This should be rarely problem, but to have a peace in mind, I would prefer separate solution.

I'm looking forward to your comments,
Honza
  • Attachment: bgtask.cpp
    (Size: 1.43KB, Downloaded 337 times)

[Updated on: Wed, 16 February 2011 13:59]

Report message to a moderator

Re: BackgroundTask [message #31244 is a reply to message #31240] Wed, 16 February 2011 15:32 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

Slightly improved version:
class BackgroundTask{
	typedef BackgroundTask CLASSNAME;
	#ifdef _MULTITHREADED
	Thread t;
	#endif
	bool running;
	const int id;
	static Index<int> list;

	void Watch(Callback task);
	static int AssignId();

	friend bool ProcessForeground(int);
public:
	void Start(Callback task);
	void Stop()                                      {int n=list.Find(id); if(n>=0) list.Remove(id);}
	int GetId()                                      {return id;}
	bool IsRunning()                                 {return running;}
	BackgroundTask():running(false),id(AssignId())   {}
	BackgroundTask(Callback task):id(AssignId())     {Start(task);}
};
Index<int> BackgroundTask::list;

void BackgroundTask::Watch(Callback task){
	running=true;
	task();
	Stop(id);
	running=false;
}

int BackgroundTask::AssignId(){
	static int sid=0;
	return sid++;
}

void BackgroundTask::Start(Callback task){
	if(IsRunning()) Stop();
	list.Add(sid);
	#ifdef _MULTITHREADED
	t.Run(THISBACK1(Watch,task));
	#else
	PostCallback(THISBACK1(Watch,task));
	#endif
}

bool ProcessForeground(int id){
#ifndef _MULTITHREADED
	Ctrl::ProcessEvents();
#endif
	return BackgroundTask::list.Find(id)>=0;
}

It allows stopping tasks individually based on unique ID. Also reusing the task instances should work now. The major difference is that ProcessForeground now takes task ID as argument.

Honza

EDIT: Removed file due to contained errors

[Updated on: Wed, 16 February 2011 16:01]

Report message to a moderator

Re: BackgroundTask [message #31245 is a reply to message #31244] Wed, 16 February 2011 15:41 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
1. I would not bother with ST here. 'background' processing with timerqueue is way too different from MT IMO to try to reconcile both methods in the single class.
2. Having said that, I do not see any advantage of using BackgroundTask over using plain Thread...
Re: BackgroundTask [message #31248 is a reply to message #31245] Wed, 16 February 2011 16:00 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

mirek wrote on Wed, 16 February 2011 15:41

1. I would not bother with ST here. 'background' processing with timerqueue is way too different from MT IMO to try to reconcile both methods in the single class.
2. Having said that, I do not see any advantage of using BackgroundTask over using plain Thread...

Let me start with the second point: The advantage is that it can be compiled in ST where Thread is not defined.

The goal of this actually IS to provide single interface for both MT and ST solutions. I am aware that it doesn't solve every possible scenario, but I think there is non-trivial group of cases where this might be handy. If extended with couple of Callbacks (WhenFinished,WhenProgress,WhenStopped), it might be a good way to manage simple tasks e.g. data loading or processing.

BTW: The above code contained couple errors, they are fixed in the attachment.
  • Attachment: bgtask.cpp
    (Size: 1.75KB, Downloaded 225 times)
Re: BackgroundTask [message #31268 is a reply to message #31248] Thu, 17 February 2011 18:31 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3356
Registered: August 2008
Senior Veteran
Hello

Not the same but similar is the gif animation in RasterPLayer. See Reference/AnimatedClip demo.

RasterPlayer::SetMT() method if compiled with MT, chooses ST or MT (if compiled with ST, only ST is available Smile).


Best regards
IƱaki
Re: BackgroundTask [message #31270 is a reply to message #31268] Thu, 17 February 2011 19:17 Go to previous message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

koldo wrote on Thu, 17 February 2011 18:31

Hello

Not the same but similar is the gif animation in RasterPLayer. See Reference/AnimatedClip demo.

RasterPlayer::SetMT() method if compiled with MT, chooses ST or MT (if compiled with ST, only ST is available Smile).

Yep, very similar idea Smile BackgroundTask could actually have the SetMT() method as well, if desired. But I think it would be a bit against the original idea (to provide uniform way to manage background tasks with most effective technology based on MT flag presence).

Honza
Previous Topic: Question: Simple plugin implementation
Next Topic: Ide MT
Goto Forum:
  


Current Time: Thu Apr 18 13:35:31 CEST 2024

Total time taken to generate the page: 0.02332 seconds