# C#/WPF GUI locking up



## FordGT90Concept (Apr 24, 2012)

I can't figure this one out. 

Basically, the GUI has a "Generate" button which contains this code:

```
if ((string)btnGenerate.Content == "Generate")
            {
                blkMessage.Text = "Started.";
                _Attempts = 1;
                _HasPassword = false;
                [b]_Rules.StartPasswordGenerator();[/b]
                btnGenerate.Content = "Stop";
            }
            else
            {
                _HasPassword = true;
                _Rules.Halt();
                blkMessage.Text = "User stopped.";
                btnGenerate.Content = "Generate";
            }
```

Here is StartPasswordGenerator():

```
_Stop = false;
            Static.LengthMin = Convert.ToUInt16(MinimumLength.Text);
            Static.LengthMax = Convert.ToUInt16(MaximumLength.Text);
            Static.MaxAttempts = Convert.ToInt32(MaxAttempts.Text);

            // Generate valid character list.
            List<char> charlist = new List<char>();
            if (AlphaLower.IsEnabled)
                charlist.AddRange(AlphaLower.Text);
            if (AlphaUpper.IsEnabled)
                charlist.AddRange(AlphaUpper.Text);
            if (Numeric.IsEnabled)
                charlist.AddRange(Numeric.Text);
            if (Special.IsEnabled)
                charlist.AddRange(Special.Text);

            Static.ValidChars = charlist.ToArray();

            Static.Random = new Random();
            for (int i = 0; i < Environment.ProcessorCount; i++)
            {
                _Threads[i] = new Thread(this.GeneratePassword);
                _Threads[i].Start();
            }
```
As you can see, it creates eight asynchronous threads (or how many processors you got) at the end there.  At this point, the GUI should be free to go about its updating.  It should be idle except for the events hitting the update sub.  But, it isn't.  It's all locked up until it finishes.

Here's the code that does the majority of the updating:

```
private void _Rules_AttemptFinished(string password)
        {
            if (blkMessage.Dispatcher.CheckAccess())
            {
                if (!_HasPassword)
                {
                    if (_Attempts == Static.MaxAttempts)
                    {
                        _Rules.Halt();
                        prgPassword.Maximum = Static.MaxAttempts;
                        prgPassword.Value = _Attempts;
                        blkMessage.Text = "Max attempts reached.  No password found matching the given requirements.";
                        btnGenerate.Content = "Generate";
                    }
                    else
                    {
                        prgPassword.Maximum = Static.MaxAttempts;
                        prgPassword.Value = _Attempts;
                        blkPassword.Text = _Attempts + "/" + Static.MaxAttempts + " (" + Math.Round(_Attempts / Static.MaxAttempts * (double)100, 2).ToString() + "%)"; 
                        _Attempts++;
                    }
                }
            }
            else
                blkMessage.Dispatcher.Invoke(new AttemptFinishedHandler(_Rules_AttemptFinished), password);
        }
```

I have verified the GUI elements are being updated but those updates aren't translating to the GUI.


Anyone have any ideas?


----------



## Kreij (Apr 24, 2012)

Is _Rules_AttemptFinished() running in the same thread as the GUI and blocking it until CheckAcess() returns true for all the threads?

Hard to tell exactly what's going on without seeing all the code. :/


----------



## FordGT90Concept (Apr 24, 2012)

It should be hitting that asynchronously.  It will crash if the invoke isn't there so it is definitely coming from a different thread.

Good point though.  Clearly the GUI is waiting for something.


I know it is updating the values in there but the values aren't translating to the GUI because it is locked up.


----------



## W1zzard (Apr 24, 2012)

when it's stuck hit pause in the debugger and switch to your main thread, look at call stack to see what's happening


----------



## Kreij (Apr 24, 2012)

It's definitely the _Rules_AttemptFinished method.
Looks like you are invoking the handler on the same dispatcher that blkPassword is associated with, which would be the GUI thread. No?


----------



## FordGT90Concept (Apr 24, 2012)

I tried blkPassword, prgPassword, this, and blkMessage.  All should be the MainWindow thread dispatcher and all have the same effect.

Edit: it does complicate things having so many GUI elements updated by one event.  Firing off many events just to update each doesn't make any sense though when one should be able to handle all.



W1zzard said:


> when it's stuck hit pause in the debugger and switch to your main thread, look at call stack to see what's happening


"Switch to main thread?"  How do you do that in Visual Studio?


----------



## Kreij (Apr 24, 2012)

blkMessage.Dispatcher.Invoke is fireing off the handler in the GUI thread isn't it?
Your getting blkMessage's Dispatcher which is the main GUI thread.

Go to tools->Settings->Expert Settings. You get a pause button for the debugger then so you can look at the stack trace (or whatever).


----------



## FordGT90Concept (Apr 24, 2012)

Is it possible blkMessage, blkPassword, and prgPassword have separate dispatchers?  You'd think it would be throwing cross reference errors if that were the case.


----------



## Kreij (Apr 24, 2012)

They are all declared in the XAML, so I would assume they are all on the GUI thread.
You're invoking back to the the GUI thread from the GUI thread, so no cross reference exceptions, just blocking the GUI from continuing.

Try moving _Rules_AttemptFinished to the class, fire it off as a thread and let it invoke to the GUI from its own process thread?

I know deep in your heart you love WPF and XAML, Ford. 
(Never did figure out that !@#$ mystery row in the Sims3 datagrid. lol)

Not sure why you are mutli-threading based on processor count, the process manager is cramming everything on one core on my machine anyway.


----------



## FordGT90Concept (Apr 24, 2012)

Kreij said:


> Try moving _Rules_AttemptFinished to the class, fire it off as a thread and let it invoke to the GUI from its own process thread?


Uh, what?  XD

I dug into what W1zzard said...Debug->Windows->Threads

MainThread appears to be stuck on System.RuntimeType.GetMethodBase().  I'm going to try naming them to disambiguate all the worker threads...(process of elimination).




Kreij said:


> I know deep in your heart you love WPF and XAML, Ford.
> (Never did figure out that !@#$ mystery row in the Sims3 datagrid. lol)


I like the end result but the steps to get there are a "!@#$"  Either my understanding of it is too weak or it just is that buggy/peculiar.  Then again, it seems like I'm the only one running into all these issues so maybe it's just me. 

Conclusion: WPF hates me. 


Edit: GenPW# are my workers.

```
Unflagged		7204	6	Worker Thread	vshost.RunParkingWindow	[Managed to Native Transition]	Normal
Unflagged		0	0	Unknown Thread	[Thread Destroyed]		
Unflagged		7468	2	Worker Thread	<No Name>		Highest
Unflagged		8052	3	Worker Thread	<No Name>		Normal
Unflagged	>	7112	8	Main Thread	Main Thread	RandomPasswordGenerator.MainWindow._Rules_AttemptFinished	Normal
Unflagged		7540	7	Worker Thread	.NET SystemEvents	[Managed to Native Transition]	Normal
Unflagged		4700	9	Worker Thread	GenPW0	RandomPasswordGenerator.MainWindow._Rules_AttemptFinished	Normal
Unflagged		4608	10	Worker Thread	GenPW1	RandomPasswordGenerator.MainWindow._Rules_AttemptFinished	Normal
Unflagged		2520	11	Worker Thread	GenPW2	RandomPasswordGenerator.MainWindow._Rules_AttemptFinished	Normal
Unflagged		6996	12	Worker Thread	GenPW3	RandomPasswordGenerator.MainWindow._Rules_AttemptFinished	Normal
Unflagged		7392	14	Worker Thread	GenPW5	RandomPasswordGenerator.MainWindow._Rules_AttemptFinished	Normal
Unflagged		4432	13	Worker Thread	GenPW4	RandomPasswordGenerator.MainWindow._Rules_AttemptFinished	Normal
Unflagged		7436	15	Worker Thread	GenPW6	RandomPasswordGenerator.MainWindow._Rules_AttemptFinished	Normal
Unflagged		3724	16	Worker Thread	GenPW7	RandomPasswordGenerator.MainWindow._Rules_AttemptFinished	Normal
```


Edit: It appears that only the MainThread is hitting the bolded code block (as it should):

```
private void _Rules_AttemptFinished(string password)
        {
            if (blkMessage.Dispatcher.CheckAccess())
            {
                [b]if (!_HasPassword)
                {
                    if (_Attempts == Static.MaxAttempts)
                    {
                        _Rules.Halt();
                        prgPassword.Maximum = Static.MaxAttempts;
                        prgPassword.Value = _Attempts;
                        blkMessage.Text = "Max attempts reached.  No password found matching the given requirements.";
                        btnGenerate.Content = "Generate";
                    }
                    else
                    {
                        prgPassword.Maximum = Static.MaxAttempts;
                        prgPassword.Value = _Attempts;
                        blkPassword.Text = _Attempts + "/" + Static.MaxAttempts + " (" + Math.Round(_Attempts / Static.MaxAttempts * (double)100, 2).ToString() + "%)"; 
                        _Attempts++;
                    }
                }[/b]
            }
            else
                [u]blkMessage.Dispatcher.Invoke(new AttemptFinishedHandler(_Rules_AttemptFinished), password);[/u]
        }
```
All the workers are sitting on the underlined line (there's 8 of them versus me so they can complete their work and get back there faster than I can click).

I see nothing out of the ordinary. 


Edit: Every time I start and pause it, the main thread is on this line:
prgPassword.Value = _Attempts;

That is out of the ordinary...


Edit: Now prgPassword.Value says Value = Cannot evaluate expression because the code of the current method is optimized.


----------



## Kreij (Apr 24, 2012)

When I pause the debugger on GUI freeze, the stack trace is sitting in _Rules_AttemptFinished. (shrug)

What I meant was move that method into the "Rules" class and call it from there as a seperate thread so the handler runs out of the GUI thread. The invokes to the GUI elements will e the only thing using GUI thread proc time and should remove the burden on the GUI thread.

Off topic : Your program crashes my processor monitoring program with out of range exceptions. rofl



> Edit: Every time I start and pause it, the main thread is on this line:
> prgPassword.Value = _Attempts;



In which half of the if statement? Maybe the method is just being locked up too as it runs on the main thread.


----------



## FordGT90Concept (Apr 24, 2012)

Yeah, mine too.  On my computer, you have 8 threads telling the MainThread to get in there too.  So more than likely, it is going to be in _Rules_AttemptFinished...

But, that can't be right.  The work the Generate Passwords are doing should be substantially heavier than displaying it.  I think something is bogging down the MainThread in the GUI but what?


Move _Rules_AttemptFinished to Rules?  How can Rules class modify the GUI?  It would almost be identical to the way it is now in both classes but with a duplicate. 


It loads any CPU to 100%.  If an application can't tolerate being out processed, I guess it will crash. XD


Oh, didn't see it was in there twice.  Every time I stop/go, it is on one line or the other that is underlined:

```
private void _Rules_AttemptFinished(string password)
        {
            if (this.Dispatcher.CheckAccess())
            {
                if (!_HasPassword)
                {
                    if (_Attempts == Static.MaxAttempts)
                    {
                        _Rules.Halt();
                        prgPassword.Maximum = Static.MaxAttempts;
                        prgPassword.Value = _Attempts;
                        blkMessage.Text = "Max attempts reached.  No password found matching the given requirements.";
                        btnGenerate.Content = "Generate";
                    }
                    else
                    {
                        _Attempts++;
                        prgPassword.Maximum = Static.MaxAttempts;
                        [u]prgPassword.Value = _Attempts;[/u]
                        blkPassword.Text = _Attempts + "/" + Static.MaxAttempts + " (" + Math.Round(_Attempts / Static.MaxAttempts * (double)100, 2).ToString() + "%)"; 
                    }
                }
            }
            else
                [u]this.Dispatcher.Invoke(new AttemptFinishedHandler(_Rules_AttemptFinished), password);[/u]
        }
```

Random thought: Is something I'm doing causing the entire tree to redraw instead of just blkPassword, prgPassword, and blkMessage?  Maybe I'm effectively spamming the GUI?  Maybe I should update only every 1000 or something.


Edit: I think that has something to do with it.  Every 1000, it was doing 100,000 in about 3 seconds instead of probably 15.  At 10,000, it updated right at the start (could see the button change to Stop), I then saw one update at the end flash for a fraction of a second before switching to the Maximum message.


Another random thought: I wonder if the event is being flooded?


Edit: I changed it to 1,000,000 attempts and it does manage to update it once in a while but the GUI is still largely froze.


Edit: I think you are right.  I some how need to consolidate all the information and only send some of it to the GUI.  I think it's getting sent too many update requests for it to manage.

It took a while for what you meant to sink in.


----------



## Kreij (Apr 24, 2012)

I guess you could be spamming the GUI. But I don't see anything that would be doing that.
Could be different in WPF I suppose. Would seem silly to redraw everything in a specific element invoke.

Program does not load any core to 100%, I'm getting negative values that are causing the exception. lol

I are tired Ford. Chemo is making life difficult. Forgive me if I'm not explaining well. 
What I meant was to put the _R_AF method in the class, launch it as a seperate thread from the main thread and then invoke to the GUI elements. May be redundant as you say if the handler is already running in a seperate process. I forget if that's the case. (sigh)


----------



## FordGT90Concept (Apr 24, 2012)

Aw, sorry. 

I'm working on moving as much of the code to RuleBook as possible and, from RuleBook, only send update info once in a while.  Hopefully it will fix the issue.

Really?  It doesn't load any core to 100%?  Maybe it's loading the GPU to 100%?   If the GPU isn't rendering it fast enough, it's holding back the MainThread which is holding back the other 8 WorkerThreads.  If it were working right, it would load the CPU to 100%. 


Edit: I think the changes I'm making is literally going to split the MainThread burden to all the WorkerThreads equally.  I'm taking all almost all the worker to the end of what the workers already do.


----------



## Kreij (Apr 24, 2012)

So we're going to move the code to OpenCL? Sounds like fun. 

Here's the program running ... Core #1 was doing the most work.


----------



## FordGT90Concept (Apr 24, 2012)

Yay! I think I got it fixed!  Here's what I looks like when I ran with the new code:





See the spike on all cores?  That was *1,000,000* passwords created and discarded in approximately 3.27 seconds!  The GUI was holding everything up.

The GUI code now only contains the following:

```
private void _Rules_Error(string password, int attempt, int maxattempts, string progresstext, string messagetext)
        {
            if (this.Dispatcher.CheckAccess())
            {
                prgPassword.Maximum = maxattempts;
                prgPassword.Value = attempt;
                blkPassword.Text = progresstext;
                blkMessage.Text = messagetext;
                btnGenerate.Content = "Generate";

                if (password != "")
                    txtGenerated.Text = password;
            }
            else
                this.Dispatcher.Invoke(new ErrorHandler(_Rules_Error), password, attempt, maxattempts, progresstext, messagetext);
        }

        private void _Rules_AttemptFinished(int attempt, int maxattempts, string progresstext, string messagetext)
        {
            if (this.Dispatcher.CheckAccess())
            {
                prgPassword.Maximum = maxattempts;
                prgPassword.Value = attempt;
                blkPassword.Text = progresstext;
                blkMessage.Text = messagetext;
            }
            else
                this.Dispatcher.Invoke(new AttemptFinishedHandler(_Rules_AttemptFinished), attempt, maxattempts, progresstext, messagetext);
        }
```

The code on the backside:

```
private void ConsolidatedUpdate(string password)
        {
            if (!_FinishSent)
            {
                _Attempts++;
                if (_Attempts >= Static.MaxAttempts)
                {
                    _FinishSent = true; // Makes all threads that hit here do nothing.
                    _Stop = true;
                    ErrorHandler h = Error;
                    if (h != null)
                        h("", _Attempts, Static.MaxAttempts, _Attempts + "/" + Static.MaxAttempts + " (" + Math.Round(_Attempts / Static.MaxAttempts * (double)100, 2).ToString() + "%)", "Max attempts reached.  No password found matching the given requirements.");
                }
                else
                {
                    if (_Attempts % 1000 == 0)
                    {
                        AttemptFinishedHandler h = AttemptFinished;
                        if (h != null)
                            h(_Attempts, Static.MaxAttempts, _Attempts + "/" + Static.MaxAttempts + " (" + Math.Round(_Attempts / Static.MaxAttempts * (double)100, 2).ToString() + "%)", "Working...");
                    }

                    if (password.Length > 0)
                    {
                        ErrorHandler err = Error;
                        if (err != null)
                            err(password, _Attempts, Static.MaxAttempts, _Attempts + "/" + Static.MaxAttempts + " (" + Math.Round(_Attempts / Static.MaxAttempts * (double)100, 2).ToString() + "%)", "Password created!");
                        _FinishSent = true;
                        _Stop = true;
                    }
                }
            }
        }
```
As you can see, ConsolidatedUpdate() which is called by all the worker threads does all the work now.

It still can only update every 1000.  I tried every single one and it locked the GUI up. Considering how fast it can generate passwords, I think I'll drop it to 10,000.


Edit: Me so happy!


----------



## Aquinus (Apr 24, 2012)

Do you have thread safe checks enabled? I've actually been writing a multi-threaded application in Java. I find that threading in Java will let you do things that aren't thread safe, but gives you the ability to easily use semaphores and such. I don't have much of a GUI for this yet, it's more like you set some flags in the command line and you get output on both the CLI and GUI. It needs improvement. Also I only use about 85% of my CPU resources on 4 threads (with a mobile i5, dual core w/ hyperthreading,) but it even scales on a 16-threaded server I have access to, but same deal, 15% unused. Have to find something for the CPU to do in that time. 





Pardon the Mac, it just happens to be the system I'm working on right now. This application so far as run on Windows 7, Ubuntu Server 11.10, and OS X. The joy of Java.


----------



## FordGT90Concept (Apr 24, 2012)

Thread safe checks are enabled by default for .NET applications and everything my app does is thread-safe.  You have to disable them if you don't want them (highly recommended not to--promotes bad programming practices).

I'm just about ready to release this application.  Just have to make a main application icon.  It'll be posted under General Software soon.


----------



## Aquinus (Apr 24, 2012)

FordGT90Concept said:


> Thread safe checks are enabled by default for .NET applications and everything my app does is thread-safe.  You have to disable them if you don't want them (highly recommended not to--promotes bad programming practices).
> 
> I'm just about ready to release this application.  Just have to make a main application icon.  It'll be posted under General Software soon.



I know, I just figured I would ask because you can get some pretty bizarre behavior if you don't lock the right variables and and just start mucking with another thread's stuff. 

Does the application make random passwords or does it give the hashes for them as well? I'm trying to understand why a password generator would need to be multi-threaded other than the fact that it makes it bad-ass.


----------



## Kreij (Apr 24, 2012)

Good question Aq. C# (WPF) goes out of its way to keep things thread safe in managed code.
You can or course subvert its efforts to accomplish things if you so desire, but the documentation at MS is really clear on what calls are "dangerous".
Since Ford is using the standard APIs for threading, they are pretty safe.
Of couse with Ford, you never really are sure.


----------



## Aquinus (Apr 24, 2012)

Kreij said:


> Good question Aq. C# (WPF) goes out of its way to keep things thread safe in managed code.
> You can or course subvert its efforts to accomplish things if you so desire, but the documentation at MS is really clear on what calls are "dangerous".
> Since Ford is using the standard APIs for threading, they are pretty safe.
> Of couse with Ford, you never really are sure.



Personally, I like managing what is safe and what isn't. I don't like the language forcing me to make something thread-safe because another thread might be using it when the code might never have two threads even talk to each other (like in my case, they work on the same set of data (writing only,) but each thread is told what they're going to work on so I know that no individual write will have to race another to set that spot in memory. However I can understand why MS would opt for everything to be thread-safe.

A great example would be this:

I have a queue that contains all of the "tasks" i want my threads to do.
As each thread takes a "task", it locks, synchronizes, uses a semaphore with, what ever you want to call it, to the queue to prevent another thread from mucking with it while it gets a task.
The thread starts doing its thing and needs to set some data in our shared dataset object by calling "quick_set(int x, int y, float val)" where no checks are done to see if another thread is reading, writing, or doing anything to this set of data, because if the thread is running, nothing is reading it, and if the thread has a task to write somewhere, no other thread will touch it because there isn't another task that covers that section of data.

^-- Reason for not liking thread-safe being required, also it slows down the application when it isn't needed and might make other threads block when they don't need to. Granted this is a specific case for the application that I'm writing, which I'm sure could be done with OpenCL since most of the calculations are squares, square roots, addition, and sins of floating point numbers in a grid.


----------



## FordGT90Concept (Apr 24, 2012)

Aquinus said:


> Does the application make random passwords or does it give the hashes for them as well? I'm trying to understand why a password generator would need to be multi-threaded other than the fact that it makes it bad-ass.


It makes random passwords with restrictions.  The restrictions is what require multiple attempts and multiple attempts sounds and awful like multithreading to me. XD

In most cases, it will get the password within 30 attempts.  Making it try to achieve the impossible can be used for stress testing/benchmarking purposes.  Considering it can do 1 million attempts in 3.27 seconds means  it would max out the code (int32) in less than 3 minutes of execution.  Not really much of a benchmark but it does show how quick your processor and memory is.




Aquinus said:


> Personally, I like managing what is safe and what isn't. I don't like the language forcing me to make something thread-safe because another thread might be using it when the code might never have two threads even talk to each other (like in my case, they work on the same set of data (writing only,) but each thread is told what they're going to work on so I know that no individual write will have to race another to set that spot in memory. However I can understand why MS would opt for everything to be thread-safe.
> 
> A great example would be this:
> 
> ...


.NET does all that automatically and everything in a .NET binary can be made accessible to third party apps by simply using the "public" modifier.


----------



## Aquinus (Apr 24, 2012)

FordGT90Concept said:


> It makes random passwords with restrictions.  The restrictions is what require multiple attempts and multiple attempts sounds and awful like multithreading to me. XD
> 
> In most cases, it will get the password within 30 attempts.  Making it try to achieve the impossible can be used for stress testing/benchmarking purposes.  Considering it can do 1 million attempts in 3.27 seconds means  it would max out the code (int32) in less than 3 minutes of execution.  Not really much of a benchmark but it does show how quick your processor and memory is.



Are you just guessing what the password is? Like doing plain-text comparisons?



FordGT90Concept said:


> .NET does all that automatically and everything in a .NET binary can be made accessible to third party apps by simply using the "public" modifier.



I didn't believe access modifiers have any extra effect on threading beyond the scope of the call or object attribute. I also don't see how this applies to my case.


----------



## FordGT90Concept (Apr 24, 2012)

Aquinus said:


> Are you just guessing what the password is? Like doing plain-text comparisons?


No, it creates passwords based on rules.   It is available here: http://www.techpowerup.com/forums/showthread.php?p=2610766




Aquinus said:


> I didn't believe access modifiers have any extra effect on threading beyond the scope of the call or object attribute. I also don't see how this applies to my case.


Threading is quite irrelevant when it comes .NET interop.  You're sharing a bit of memory across multiple applications.  "Shared dataset" is as simple as making it public then calling to it by name.


----------



## Aquinus (Apr 24, 2012)

Just checked out the link. I like how it looks, good job.


----------



## FordGT90Concept (Apr 24, 2012)

Thank WPF for that.  A PITA to get working but it's worth it. XD


----------

