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 » U++ Library support » U++ MT-multithreading and servers » Code before Thread.Run() nor executed
Code before Thread.Run() nor executed [message #48661] Mon, 14 August 2017 13:23 Go to next message
rafiwui is currently offline  rafiwui
Messages: 105
Registered: June 2017
Location: Stuttgart, Germany
Experienced Member
I have these methods:
void StartGeneration()
{
	// Disable buttons
	buttonBar.generate.Enable(false);
	buttonBar.next.Enable(false);
	buttonBar.previous.Enable(false);
	
	// Switch page
	displayLayouts[buttonBar.pageIndex].Show(false);
	generationProgress.Show(true);
	
	// Setup main progress bar
	generationProgress.progressMain.Set(0, 3);
	
	// Start thread
	generationThread.Run(THISBACK(Generate));
	//Thread::Start(THISBACK(Generate));
	
	return;
}


It is called from a button click event.
My problem is that nothing but the Run()-method of the thread is executed or at least there is now visual change in my application but there should be a layout change.
Also it is kinda not started as a thread because the application "freezes" while the thread is running.
Any ideas how I can fix this?

EDIT: Because I was asked for in this thread: Here is an example application to reproduce the problem.
  • Attachment: Bugtester.7z
    (Size: 1.00KB, Downloaded 70 times)


Greetings
Daniel

[Updated on: Tue, 15 August 2017 09:06]

Report message to a moderator

Re: Code before Thread.Run() nor executed [message #48668 is a reply to message #48661] Tue, 15 August 2017 08:05 Go to previous messageGo to next message
Oblivion is currently offline  Oblivion
Messages: 664
Registered: August 2007
Location: Turkey
Contributor
Hello Daniel,

Again this information is not really enough. Smile
What does Generate() do, and how does it?
If I may presume it is manipulating the UI, then there are rules your thread needs to obey.
It is really hard to say anything based on this code snippet.

Best regards,
Oblivion


[Updated on: Tue, 15 August 2017 08:06]

Report message to a moderator

Re: Code before Thread.Run() nor executed [message #48669 is a reply to message #48668] Tue, 15 August 2017 09:07 Go to previous messageGo to next message
rafiwui is currently offline  rafiwui
Messages: 105
Registered: June 2017
Location: Stuttgart, Germany
Experienced Member
Sorry. I thought it would be enough Confused
Added an valid example as zipped folder for you Wink


Greetings
Daniel
Re: Code before Thread.Run() nor executed [message #48671 is a reply to message #48669] Tue, 15 August 2017 18:45 Go to previous messageGo to next message
Oblivion is currently offline  Oblivion
Messages: 664
Registered: August 2007
Location: Turkey
Contributor
As I suspected, you are calling GUI elements/methods from a worker thread directly. You need to use PostCallback, and make sure the thread terminates.
Here you go:

TestLayout::TestLayout()
{
	CtrlLayout(*this);
	button1 << THISBACK(OnCLickButton);
}

void TestLayout::OnCLickButton()
{
	WhenThreadStart();
}


TestLayout2::TestLayout2()
{
	CtrlLayout(*this);
	progress.Set(0, 1);
}

TestWindow::TestWindow()
{
	SetRect(0, 0, Zx(400), Zy(200));
	Add(testLayout);
	Add(testLayout2);
	testLayout.Show(true);
	testLayout2.Show(false);
	testLayout.button1.WhenAction = THISBACK(StartProgress); // button1's WhenAction callback was not defined.
}

void TestWindow::StartProgress()
{
	testLayout.Show(false);
	testLayout2.Show(true);
	testLayout2.progress.Set(0, 10); 
	Thread().Run(THISBACK(Progress));
}

void TestWindow::Progress()
{
	// This thread code could be written in a much better way, but I'm simply giving you the idea :). 
	for(int i = 0; i < 10; i++)
	{
		if(Thread::IsShutdownThreads())
			break;
		Sleep(1000);
		PostCallback([=]{ 
		    // Never directly call GUI elements. If wou want to do fancy GUI stuff with
		    // threads, use PostCallback. 
			testLayout2.progress++;

		});
	}
	PostCallback([=]{	
			// Let us roll-back;
			testLayout2.Hide();
			testLayout.Show();
	});

}

TestWindow::~TestWindow()
{
	// Make sure that running threads terminate.
	if(Thread::GetCount())
		Thread::ShutdownThreads();
}


Best regards,
Oblivion


[Updated on: Wed, 16 August 2017 07:47]

Report message to a moderator

Re: Code before Thread.Run() nor executed [message #48672 is a reply to message #48671] Wed, 16 August 2017 09:43 Go to previous messageGo to next message
rafiwui is currently offline  rafiwui
Messages: 105
Registered: June 2017
Location: Stuttgart, Germany
Experienced Member
I changed the code to your code but still no layout change. So the main problem persists.
Any idea why?


Greetings
Daniel
Re: Code before Thread.Run() nor executed [message #48709 is a reply to message #48671] Sat, 26 August 2017 13:16 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12506
Registered: November 2005
Ultimate Member
Oblivion wrote on Tue, 15 August 2017 18:45
As I suspected, you are calling GUI elements/methods from a worker thread directly. You need to use PostCallback, and make sure the thread terminates.


Actually, for some time now many methods can be called in non-main thread, with GuiLock. Exception are window creation and event loop related things (the reason there is still the same: Windows associates event loop to the thread that created the window).
Re: Code before Thread.Run() nor executed [message #48710 is a reply to message #48672] Sat, 26 August 2017 13:16 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12506
Registered: November 2005
Ultimate Member
rafiwui wrote on Wed, 16 August 2017 09:43
I changed the code to your code but still no layout change. So the main problem persists.
Any idea why?


Can you post a package here?

Mirek
Re: Code before Thread.Run() nor executed [message #48715 is a reply to message #48710] Mon, 28 August 2017 08:38 Go to previous messageGo to next message
rafiwui is currently offline  rafiwui
Messages: 105
Registered: June 2017
Location: Stuttgart, Germany
Experienced Member
mirek wrote on Sat, 26 August 2017 13:16

Can you post a package here?

Here you go Wink
  • Attachment: Bugtester.7z
    (Size: 1.11KB, Downloaded 61 times)


Greetings
Daniel
Re: Code before Thread.Run() nor executed [message #48716 is a reply to message #48715] Mon, 28 August 2017 09:27 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12506
Registered: November 2005
Ultimate Member
There is only a small typo: You have assigned StartProgress to TestLayout instead of button1:

TestWindow::TestWindow()
{
	SetRect(0, 0, Zx(400), Zy(200));
	Add(testLayout);
	Add(testLayout2);
	testLayout.Show(true);
	testLayout2.Show(false);
	testLayout.button1.WhenAction = THISBACK(StartProgress);
}


Here are some further hints:

TestWindow::TestWindow()
{
	SetRect(0, 0, Zx(400), Zy(200));
	Add(testLayout);
	Add(testLayout2);
	testLayout.Show(true);
	testLayout2.Show(false);
	testLayout.button1 << [=] {
		testLayout.Show(false);
		testLayout2.Show(true);
		testLayout2.progress.Set(0, 100);
		Thread::Start([=] {
			for(int i = 0; i < 100; i++) {
				if(Thread::IsShutdownThreads())
					break;
				Sleep(100);
				GuiLock __;
				testLayout2.progress++;
			}
			GuiLock __;
			testLayout.Show(true);
			testLayout2.Show(false);
		});
	};
}
Re: Code before Thread.Run() nor executed [message #48717 is a reply to message #48716] Mon, 28 August 2017 09:39 Go to previous messageGo to next message
rafiwui is currently offline  rafiwui
Messages: 105
Registered: June 2017
Location: Stuttgart, Germany
Experienced Member
Quote:
There is only a small typo: You have assigned StartProgress to TestLayout instead of button1:

... Neutral
Thanks for finding that stupid mistake Laughing


Greetings
Daniel
Re: Code before Thread.Run() nor executed [message #48719 is a reply to message #48717] Mon, 28 August 2017 10:51 Go to previous messageGo to next message
rafiwui is currently offline  rafiwui
Messages: 105
Registered: June 2017
Location: Stuttgart, Germany
Experienced Member
How exactly does GuiLock work? Because when I tried to implement it in my application it doesn't work. Is there a documentation?
EDIT:
This is part of the code I use:
void MainWindow::Generate()
{
	// Generate
	GuiLock __;
	progress.progressMainLabel.SetText(t_("(0/3) Generating first..."));
	if(!GenerateFirst())
	{
		AbortGeneration(1);
		return;
	}
	progress.progressMain++;
	progress.progressMainLabel.SetText(t_("(1/3) Generating second..."));
	if(!Second())
	{
		AbortGeneration(2);
		return;
	}
	progress.progressMain++;
	progress.progressMainLabel.SetText(t_("(2/3) Generating third..."));
	if(!GenerateThird())
	{
		AbortGeneration(3);
		return;
	}
	progress.progressMain++;
	progress.progressMainLabel.SetText(t_("(3/3) Done"));
}

Instead of showinf every step it just generates all three and at the end updates the gui. So what do I have to change that every step it is updated?


Greetings
Daniel

[Updated on: Mon, 28 August 2017 11:00]

Report message to a moderator

Re: Code before Thread.Run() nor executed [message #48723 is a reply to message #48719] Tue, 29 August 2017 17:20 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12506
Registered: November 2005
Ultimate Member
rafiwui wrote on Mon, 28 August 2017 10:51
How exactly does GuiLock work? Because when I tried to implement it in my application it doesn't work. Is there a documentation?
EDIT:
This is part of the code I use:
void MainWindow::Generate()
{
	// Generate
	GuiLock __;
	progress.progressMainLabel.SetText(t_("(0/3) Generating first..."));
	if(!GenerateFirst())
	{
		AbortGeneration(1);
		return;
	}
	progress.progressMain++;
	progress.progressMainLabel.SetText(t_("(1/3) Generating second..."));
	if(!Second())
	{
		AbortGeneration(2);
		return;
	}
	progress.progressMain++;
	progress.progressMainLabel.SetText(t_("(2/3) Generating third..."));
	if(!GenerateThird())
	{
		AbortGeneration(3);
		return;
	}
	progress.progressMain++;
	progress.progressMainLabel.SetText(t_("(3/3) Done"));
}

Instead of showinf every step it just generates all three and at the end updates the gui. So what do I have to change that every step it is updated?


That is because is GUI is blocked while GuiLock is active...

GuiLock is "guard class" - it locks GUI mutex in constructor and releases it in destructor. While that mutex is locked, GUI is stopped and you can meddle with variables that GUI accesses (without using PostCallback).

In above function, you lock GUI at the start of function and unlock it at the end. That is why the GUI is only updated when Generate ends...
Re: Code before Thread.Run() nor executed [message #48724 is a reply to message #48723] Tue, 29 August 2017 18:21 Go to previous messageGo to next message
rafiwui is currently offline  rafiwui
Messages: 105
Registered: June 2017
Location: Stuttgart, Germany
Experienced Member
And how can I unlock it inside the function?

Greetings
Daniel
Re: Code before Thread.Run() nor executed [message #48725 is a reply to message #48724] Tue, 29 August 2017 20:26 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12506
Registered: November 2005
Ultimate Member
rafiwui wrote on Tue, 29 August 2017 18:21
And how can I unlock it inside the function?


Put it into the block.

{
GuiLock __;
do something
} // destructor unlocks

Alternatively, GuiLock is really simple:

struct GuiLock {
	GuiLock()  { EnterGuiMutex(); }
	~GuiLock() { LeaveGuiMutex(); }
};


You can call EnterGuiMutex() / LeaveGuiMutex() directly too...

BTW, note that "__" is my way of saying "name does not matter".

Mirek
Re: Code before Thread.Run() nor executed [message #48726 is a reply to message #48725] Tue, 29 August 2017 20:30 Go to previous message
rafiwui is currently offline  rafiwui
Messages: 105
Registered: June 2017
Location: Stuttgart, Germany
Experienced Member
mirek wrote on Tue, 29 August 2017 20:26

You can call EnterGuiMutex() / LeaveGuiMutex() directly too...

Ok thanks.

mirek wrote on Tue, 29 August 2017 20:26

BTW, note that "__" is my way of saying "name does not matter".

Yeah I thought so Very Happy


Greetings
Daniel
Previous Topic: How to use TLS over SMTP
Next Topic: HttpRequest ignores server errors
Goto Forum:
  


Current Time: Mon Jun 01 17:40:21 CEST 2020

Total time taken to generate the page: 0.01132 seconds