On Sun, 28 Jun 2020 07:27:28 GMT, Adnan wrote:

For the last couple weeks I have remained unsuccessful in emulating a download progressbar.

Everything usually works but in some cases my progressbar does not advance, and I have absolutely no idea why. I don't even know where to start so I need help here.

Because the code would only sometimes get stuck randomly, I have wrapped the main inside a loop.

import gio.Application : GioApplication = Application;
import gtk.Application : Application;
import gtk.ApplicationWindow : ApplicationWindow;
import gtk.ProgressBar : ProgressBar;
import glib.Timeout : Timeout;
import gtkc.gtktypes : GApplicationFlags, GPriority;

debug import std.stdio;

class Downloader
{
	string[] links = [
		`link1`, `link2`, `link3`, `link4`, `link1`, `link2`, `link3`, `link4`,
		`link1`, `link2`, `link3`, `link4`, `link1`, `link2`, `link3`, `link4`,
		`link1`, `link2`, `link3`, `link4`, `link1`, `link2`, `link3`, `link4`,
		`link1`, `link2`, `link3`, `link4`, `link1`, `link2`, `link3`,
		`link4`, `link1`, `link2`, `link3`, `link4`,
	];
	private shared size_t completed = 0;

	double getFraction()
	{
		return cast(double) completed / links.length;
	}

	size_t getCompleted()
	{
		return cast(size_t) completed;
	}

	static void start(ref Downloader downloader)
	{
		import std.parallelism : parallel;
		import core.thread : Thread, seconds;

		{
			// emulate HTTP response overhead;
			Thread.sleep(seconds(2));
		}
		synchronized
		{
			// emulate random Download time
			import std.random : Random, uniform;

			auto rnd = Random(4361);

			foreach (_; downloader.links.parallel())
			{
				Thread.sleep(uniform(0, 6, rnd).seconds());
				++cast() downloader.completed;
			}
			debug writeln(`Download finished`);
		}
	}
}

class ProgressIndicatorBar : ProgressBar
{
	this()
	{
		super.setShowText(true);
		super.setPulseStep(0.2);
	}
}

class PrimaryWindow : ApplicationWindow
{
	const int width = 320, height = 100;
	ProgressIndicatorBar pib;
	this(Application app)
	{
		super(app);
		super.setSizeRequest(width, height);
		scope (success)
			super.showAll();

		pib = new ProgressIndicatorBar();
		scope (success)
			add(pib);

		auto downloader = new Downloader();

		import std.parallelism : task;

		auto downloadTask = task!(Downloader.start)(downloader);
		downloadTask.executeInNewThread();

		auto timeout = new Timeout(100, delegate bool() {
			const auto completed = downloader.getCompleted();
			debug writefln!"Completed: %s of: %s"(completed, downloader.getCompleted());
			if (completed < downloader.links.length)
			{
				if (completed == 0)
				{
					pib.setText(`Awaiting response...`);
					pib.pulse();
				}
				else
				{
					pib.setText(`Downloading...`);
					pib.setFraction(downloader.getFraction());
				}
				return true;
			}
			else
			{
				super.setTitle(`Downloading complete`);
				// pib.setShowText(false);
				pib.setVisible(false);
				super.destroy();
				return false;
			}
		}, GPriority.HIGH);
	}
}

void main(string[] args)
{
	while (true)
	{
		auto application = new Application(`org.gitlab.helloprogressbar`,
				GApplicationFlags.FLAGS_NONE);
		application.addOnActivate(delegate void(GioApplication app) {
			auto appWindow = new PrimaryWindow(application);
		});
		const auto _ = application.run(args);
	}
}

Now note that the cases where it gets stuck, the actual download function reports that the download finished (after the parallel foreach). Inside my timeout, I also see that completed == 34 of 34 in the stdout prints.

YET the progressbar gets stuck some times.

Note that those "Completed 34 of 34" lines are live, it keeps printing but the progressbar is stuck. The UI is still responsive.

Nevermind, I was printing the same value twice