DFL background tasks

Scroph via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Jun 10 15:18:20 PDT 2015


Briliant, thanks a lot ! Looks like I misunderstood Adam's reply, 
sorry about that !

I tried different things but I didn't think of calling invoke 
from within the worker thread, that solved the freezing problem. 
I ended up using the Thread class; spawn complained about the 
mutability of the given arguments. I realize what I did may be an 
ugly solution for the problem at hand, so I'll try to modify the 
code in order to avoid giving the thread UI elements altogether, 
thus being able to take advantage of more.. modern techniques 
like std.concurrency.

I'm using the Timer trick on another part of the project. Right 
now I'm running instances of a "Downloader" class in the 
background, a class that extends Thread and provides some useful 
functionality : a way to track the progress, to set rate limits, 
to abort the download, etc. It seems to be working fine, I'm 
using the (incomplete) program to download Visual Studio as we 
speak.

I set up a timer to periodically retrieve the progress of a 
download from the instances then update the ListView accordingly. 
Right now I'm hesitating between continuing with this approach vs 
using std.concurrency or even std.parallelism since the downloads 
are supposed to run in parallel without communicating with one 
another, but the only way I see would be to place the message 
handling code inside a loop, which for some reason doesn't sit 
right with me. I'm still learning concurrency (courtesy of Ali 
Çehreli and his book), so maybe my doubts are unfounded. Here's 
what I'll probably end up using, minus the error handling :

void dlWorker(HTTP client, string local, string remote, bool 
resume = true)
{
	auto fh = File(local, resume ? "a" : "w");
	scope(exit)
		fh.close;
	size_t size;
	size_t progress;
	client.onProgress = (size_t dlTotal, size_t dlNow, size_t 
ulTotal, size_t ulNow) {
		size = dlTotal;
		progress = dlNow;
	};
	client.onReceive = (ubyte[] data) {
		fh.rawWrite(data);
		return data.length;
	};	
	client.perform;
	while(!client.isStopped)
	{
		auto msg = receiveOnly!(MsgType, int)();
		switch(msg[0])
		{
			case MsgType.progress: send(ownerTid, progress); break;
			case MsgType.size: send(ownerTid, size); break;
			case MsgType.abort:
				client.shutdown;
				send(ownerTid, 1);
			break;
			default:
				client.handle.set(CurlOption.recv_rate_speed_large, msg[1]);
				send(ownerTid, 1);
			break;
		}
	}
}

enum MsgType
{
	progress, size, abort, limit;
}

Though I'm not entirely sure how I would tie the ListView rows to 
their respective workers. But I'll cross that bridge when I get 
to it.

Again, thanks for all the help. You guys are definitely going to 
be mentioned in the "About" section of the finished product.


More information about the Digitalmars-d-learn mailing list