Components

Aus GameBrowser - Wiki

Wechseln zu:Navigation, Suche

Inhaltsverzeichnis

BackgroundWorker

Der backgroundWorker dient dazu eine bestimmte Aufgabe isoliert von anderen Operationen auszuführen, dazu wird ein Worker in den BackgroundWorkerPool gelegt. Der Pool kann eine gewisse Anzahl an Workern im Hintergrund arbeiten lassen, diese Anzahl kann entweder im CTor des Pools angegeben werden oder beträgt die Anzahl an HardwareThreads (zB CPU Kerne).

Sind alle WorkerThreads mit Aufgaben befüllt werden Worker dem WorkerThread zugwiesen der am wenigsten zu tun hat. der WorkerThread wird wenn möglich sich den nächsten Worker nehmen und bearbeiten sobald ein alter Worker abgeschlossen wurde.

Wird ein Worker behandelt so kann dieser nach Abschluss ein Event aufrufen, das OnFinished Event. Das Event bekommt dabei als Argument den Worker selbst geliefert. Der Worker wird nach Beendigung seiner Aufgabe bzw nach abarbeiten des Events gelöscht.

Der Worker kann im Event seinen Status abfragen der 3 Stati annehmen kann: Completed, Failed (wenn beim abarbeiten eine Exception geworfen wurde) oder Canceled (muss selbst gesetzt werden).

Wozu kann man es verwenden? Langwierige Aufgaben welche sich selbst erledigen können dürfen sich als Worker bezeichnen, darunter fallen zb Downloadaktionen.

Beispiel:

  1. class DownloadJob
  2. 	: public BackgroundWorkerBase
  3. {
  4. public:
  5. 	DownloadJob(const std::string& as_Source, const std::string& as_Destination)
  6. 		: BackgroundWorkerBase()
  7. 		, mk_DownlodedFile_(NULL)
  8. 	{
  9. 	}
  10.  
  11. 	virtual void Run()
  12. 	{
  13. 		mk_DownlodedFile_ = new File(ms_Source, ms_Destination);
  14.  
  15. 		if (!mk_DownlodedFile_->Download())
  16. 			throw std::excption("Error while downloading file.");
  17. 	}
  18.  
  19. 	k_File* get_DownloadedFile() const { return mk_DownlodedFile_; }
  20.  
  21. private:
  22. 	std::string ms_Source;
  23. 	std::string ms_Destination;
  24. 	File* mk_DownlodedFile_;
  25. };
  26.  
  27. void OnDownloadFinished(BackgroundWorker ak_pJob)
  28. {
  29. 	boost::shared_ptr<DownloadJob> lk_pJob = boost::shared_dynamic_cast<DownloadJob>(ak_pJob);
  30. 	if (lk_pJob != NULL && lk_pJob->get_Status() == r_JobState::Completed)
  31. 	{
  32. 		...
  33. 	}
  34. }
  35.  
  36.  
  37.  
  38. BackgroundWorkerPool lk_DownloadWorkerPool(gi_MaxDownloads);
  39. ...
  40. DownloadJob* lk_Job_ = NULL;
  41. lk_Job_ = new DownloadJob("http://www.Mirror.de/File.dat", "./Downloads/File.dat");
  42. lk_Job_->OnFinished = boost::bind<void>(OnDownloadFinished, _1);
  43. lk_DownloadWorkerPool.QueueJob(lk_Job_);


Beachtet bitte das die Events in dem Thread abgearbeitet werden in dem auch der WorkerPool erstellt wurde. Abgearbeitet werden die Events auch nur dann wenn ein k_AsyncJobPool diese abholt (Im MainThread sollte sowieso einer arbeiten.).


AsyncJob

Das AsyncJobs System ist eine Art erweitertes nachrichtenSystem, jeder Job der in einen AsyncJobPool gelegt wird kann von diesem ausgeführt werden. Ausgeführt werden diese Jobs allerdings nicht unbedingt in dem Thread in dem sie erstellt werden sondern in dem Thread für den sie bestimmt wurden. Ohne Zusätze ist dies immer der HauptThread.

Da die Abarbeitung/Empfang der Nachrichten im Zielthread nicht ohne weiteres abläuft ist es nötig im Zielthread regelmässig folgendes aufzurufen:

  1. AsyncJobPool::get_Instance().ProcessJobs();

Hiermit ist es nun möglich relativ gefahrlos Aktionen in einem Zielthread auszuführen ohne sich um umständliche Locking-Mechanismen zu kümmern (Zum Beispiel Können so Fortschrittsmeldungen an den GUI thread gesendet werden der somit einen Fortschrittsbalken aktualisiert.).

Beispiel:

  1. class ProgressInfoJob
  2. 	: public AsyncJobBase
  3. {
  4. public:
  5. 	ProgressInfoJob(float af_Value)
  6. 		: mf_Value(af_Valuen)
  7. 	{
  8. 	}
  9.  
  10. 	virtual void Process()
  11. 	{
  12. 		UpdateProgressBar(mf_Value, 0.0f, 100.0f);
  13. 	}
  14.  
  15. private:
  16. 	float mf_Value;
  17. };
  18.  
  19.  
  20. void ProgressThread()
  21. {
  22.    AsyncJobPool& lk_JobPool = AsyncJobPool::get_Instance();
  23.    for (int i = 0; i <= 100; ++i)
  24. 	   lk_JobPool.QueueJob(new ProgressInfoJob(i / 100.0f));
  25. }

Für Einfachere Funktionsaufrufe bietet sich der SimpleFunctionCallJob an:

  1. SimpleFunctionCallJob(boost::function<void(void*)> ak_Function, void* mv_Data_ = NULL)


Async Download

  1. void OnDownloadFinished(tk_BackgroundWorker ak_pJob)
  2. {
  3. 	boost::shared_ptr<ToFileDownloader> lk_pJob = boost::shared_dynamic_cast<ToFileDownloader>(ak_pJob);
  4. 	if (lk_pJob != NULL && lk_pJob->get_Status() == JobState::Finished)
  5. 	{
  6. 		std::cout << "Download completed." << std::endl;
  7. 	}
  8. 	else
  9. 		std::cout << "Download failed or canceled." << std::endl;
  10. }
  11.  
  12.  
  13. void OnDownloadProgress(std::wstring as_Source, std::wstring as_Target, size_t ar_CurrentSize, size_t ar_FinaleSize)
  14. {
  15. 	std::wcout << L"Download progress (" << as_Source << L"): " << ar_CurrentSize << L"/" << ar_FinaleSize << std::endl;
  16. }
  17.  
  18.  
  19.  
  20. boost::shared_ptr<ToFileDownloader> lk_pJob;
  21. lk_pJob = boost::shared_ptr<ToFileDownloader>(
  22. 	new ToFileDownloader(L"http://www.dras.biz/download/Ocean4k.avi", L"C:/Test.avi",
  23. 		boost::bind<void>(OnDownloadProgress, _1, _2, _3, _4))
  24. 	);
  25. lk_pJob->OnFinished = boost::bind<void>(OnDownloadFinished, _1);
  26. lk_DownloadWorkerPool.QueueJob(lk_pJob);


It is also possible to download a file to a memory/stringstream, for this use the class k_ToMemoryDownloader and call upon the finish event get_MemoryStream() to retrive the used target memory stream.


Cache

Creating the Cache class:

  1. // creates the Cache in LocalApplicationData\MyCacheDirectory\
  2. // and sets the max cache size to 50 MegaBytes
  3. Cache lk_Cache(L"MyCacheDirectory", 50);

Updating the cache (removing old date and freeing disc space):

  1. lk_Cache.CleanUp(
  2.     true, // True to delete expired data
  3.     true, // True to remove the oldest data when the cache disc space limit has been reached
  4.     false // False to disallow the deletion of every cache entrie
  5.   );

Adding a MemoryBlock or a simple k_Variant:

  1. // adds MyVariant for an unlimited expiration time into the cache
  2. lk_Cache.SetData(L"MyVariant", lk_MyVariant); 
  3.  
  4. // Adds a Datablock with the given size into the cache, this entry should expire after 3 minutes.
  5. lk_Cache.SetData(L"MyDatablock", lc_Buffer_, lul_BufferSizeInByte, 3 * 60);

Explicit removing data:

  1. lk_Cache.DeleteData(L"MyVariant");

Retriving a cache entry:

  1. // retrives a variant (use lk_Variant.IsEmpty() to check if the entry was found)
  2. Variant lk_Variant = lk_Cache.GetData(L"MyVariant");
  3.  
  4. // retrives a datablock
  5. char* lc_Data_;
  6. unsigned long lul_DataSize;
  7. bool lb_Success = lk_cache.TryGetData(L"MyDatablock", &lc_Data_, lil_DataSize);
Navigation
Media
Werkzeuge