Back in the Saddle

Wait…give me a minute…

…..UUUUUUGH….*stretch*….UHHHHHH…..and lets just add an OOFDA in there.

You may be asking yourself what the heck all that is about.  It’s my dammed body yelling at me for jumping back into the workout saddle all of a sudden like yesterday.  Oh yeah…the body is certainly angry at me today…but there’s a number of things that I need stamina for coming up and I have multiple other reasons to do it…

The absolute most important reason is my boys.  One of them made a new years resolution to workout more.  He’s done ok, but I’m not the sort that wants to have to remind my kids of their commitments…either they want to do something or they don’t and they’ll reap the benefits or the suffer the downfall accodingly.  Life’s the best teacher of wisdom there is and they need to experience it…that being said I don’t enjoy watching my kiddo’s fail…so to inspire him I decided to dive back into working out on a regular basis and to make sure he saw it.  Lead by example Toffer…lead by example…that’s what I was chanting to myself last night trying to push through level 11 on the eliptical.

Bah…level 11…I was on level 20, 3 months ago.  Damned surgery, holiday’s, sickness, loosing my first match….ALL DAMNED EXCUSES.  The plain and simple dirty truth of it all is I knowingly slacked off my good eating habits and excercising and I’m feeling it in my belt.

Then there’s kung-fu.  As I creep ever closer to my next progression, I know Sifu wants to see even better conditioning…for a guy who hates working out, this is going to be a tough one, but the boys need to see what they’re in for once they get to where I’m at…and I want to be a better training partner for them someday so I’ll push ever onward.

I tell ya…anyone reading this thing looking for a bit of inspiration, it all comes from my kiddos…so, go have a kid.  HAH!  Anyway…just figured I’d give a long overdue update on where I’ve landed on my fitness.  I made it all the way down to 260lbs at the peak of my working out…and starting from 360, I’m extremely proud of that because I pretty much just took what was being taught to me by Sifu and the various sihing around me…and really seriously applied it, putting the work in…and the short and tall of it is it worked and will continue to work as long as I continue to stick to it.  That’s the end of the story…you want to be in shape and be healthy, you eat right and workout…that’s an AND in there, not an OR…unless you work a job where you’re burning through thousands of calories a day or you’re one of those damned lucky bastards with a metabolism that burns through anything…EVERYONE needs to do something extra to burn off calories and keep muscles in tone.  End of story…anyway…I’ve probably gained back to 275 by my guess…I’m too scared to actually step on the scale, but I can feel my belt a bit tighter and that’s enough of a kick in the ass for me to put a stop to it…so that being said…

SHUT THE HELL UP BODY…you’ll do as you’re told and just deal with.  I’m living a long and healthy life to watch all my boys grow wise beyond my years.  🙂

Back in the Saddle

TravelTuesday

Just thought I’d give a shout out to a new follower…it’s crazy to follow my blog, but I thank her regardless. Love her photography…this one in particular reminds me a lot of back home in northern Minnesota. Nice work…keep it up! 🙂

TravelTuesday

Evolvinator

Hey all.

Yup…that’s all I got after having taken a pretty long haitus from writing stuff in this blog.  For a while I turned kinda health nut and lost a bunch of weight…and blogged about that stuff for a while, but that’s not what I really want to be spending my time thinking and blogging about.  I think what happened is I was finding ways to keep my brain interested in the process of eating better and exercising…because I hated it.  I’m still doing it…I still hate it…but it’s more a part of my everyday life now.  That’s how it’s gotta be if you really want to keep healthy and keep weight off…but like I said, it’s not something I’m terribly intersted in so I’m not going to actively blog about unless I have something I to say that’s burning it’s way through my fingers.

Ok, if you’re still with me…great.  This page is a landing spot for the project I kicked off with my younger kids.  The concept is that I’m going to use this as a way to show them how the coding process works.  Starting a project out in source control…designing the concept of the program and how objects should interact, coding up a framework to build from, reviewing code before it’s checked in, etc…  So far they seem to love it…unfortunately I’m a terrible teacher so they’ll have that to keep dealing with.

So the basic idea I pitched to the boys was that Evolvinator was going to be an app that has the concept of a cycle.  At the start of every cycle it creates a “Toffoid”.  The toffoid currently just exists and sits in memory…and every new cycle another is created and added to the collection.  I know…stupid…but a simple concept for an 8 and 10 year old to get their heads wrapped around.  I then said my intent is to alter the “toffoid” code so that they would start interacting…and then eventualy mutate on their own.  They were hooked.

One of them immediately started coming up with different varients of toffoids and started making artwork for them.  The other started getting really into the coding side of things and started writing his own programs to learn what my code was doing.  I’m so excited…they are showing interest in what I do for a living…well sorta.  Now I just have to figure out how to keep fostering that curiosity and not let it die.  If I can do that, they’ll have a much better jumping off point in the coding world than I did.  I always said I wish I would have gone to school for programming instead of being self taught.  There so much training in logic and patterns than a person gets while going through all the education in coding techniques that took me many years to figure out on my own.  It would be so awesome if I could give them an edge by teaching them what I know.

I’m using Microsoft accounts and Visual Studio Online for an IDE and source control.  I’m still trying to convert to the world of “git” myself so it’ll be good for me as well.

I’ll be posting code source and details about design as I go forward as well as any interesting conversations the boys and I have that I think is worth chatting about, but this is the kick off.  Enjoy!  🙂

Update 01-05-2017:

I’ve got the framework of the app down.  I have given it the concept of a cycle which is currently 10 seconds.  Every cycle it creates a “Toffoid” object.

A “Toffoid” currently consists of having a Guid for an Id and a value of 1-10 for LifePoints.  They are then added to a List<Toffoid> collection and that’s where they sit.

I made the Toffoid serializable and when the program exits it serializes created Toffoids out to a binary file…when the app starts it deserializes them back into the List<Toffoid> in memory.

That’s about all the further I’ve take it so far as I’m waiting for the kiddos to do some code review.  Idea’s we’ve talked about is having different classes derive from Toffoid to make things like a planet for other Toffoids to exist on, evolved Toffoids, non-evolving Toffoids to give the evolving ones something to stress about and give them the need to evolve.  Idea’s about land, flying, digging, and swimming variants of Toffoids have been talked about.

The term “Habaltar” has been given to Toffoids that can evolve into other things.  That’s it for now.  Possibly some artwork from the kiddos about what these things could look like if we decide to add graphics to the project.  🙂

Update 02-08-2017:

Now that the basic idea has been figured out…I decided that I really must have some way to display the stuff that’s floating around in memory…and then I decided I’m going to take that a step further and actually figure out how the Toffoids are going to exist…so Ploffoids came to be.  A ploffoid is a toffoid that other toffoid’s can live on…now how to show ploffoids.

I felt that it would be easiest to try to pick up Unity and see if I can make the graphics part work using that…to that end I went through the “Roll a Ball” tutorial and managed to create my first game with it…now I’m just trying to find a way to create a cuboid type globe…which will be my “ploffoids”.  I’ll post some more info once I figure that stuff out.  🙂

Here’s a couple of posts I’ve come across that talk about something similar to what I’m trying to do.

http://entitycrisis.blogspot.com/2011/02/uniform-points-on-sphere.html

http://answers.unity3d.com/questions/142630/sphere-made-of-cubes-algorithm.html

http://answers.unity3d.com/questions/257815/how-do-i-generate-cubes-to-form-a-sphere.html

Evolvinator

That was a long journey…

Well folks…as you may know from reading my FB, I’ve reached my 265 lb goal.  I’m calling this a 95 lb weight loss, even though I only have documented proof of 80 lbs of it…I know I was around 360 when I started kungfu…and that’s what I’m using as the starting point for my weight loss journey.

I like to reflect on things whenever I get through something difficult.  For some people weight loss may not be difficult…but this time through has been the single most difficult thing I’ve ever had to do, but it was pretty much only mental.  I’ve half heartedly made attempts to loose weight in the past with some success, but not really.  As apparent, I was pretty serious about it this time…but what made it so difficult was my unending desire to binge snack.  It’s what has been my stress reliever for most of my life and I’ve been denying myself that stress relief for almost a year now.

What did I do so different this time?  Honestly I think it was when I started really paying attention to the calories I consume vs the calories I burn in a day by day basis.  When I really looked at the food I was eating and the amount of calories in it and I used a fitness band to track the calories I burned during exercise to get a good idea of how much I was really burning through…rather than just guessing…I finally understood that pizza was really some destructive nasty stuff that was invented by aliens to fatten humans up for feasting on.  Ok, not really…but I understood that if I was going eat half a large pizza, I probably just consumed 5000-8000 calories (depending on the pizza) and that I now had a debt of 1 1/2 – 2 1/2 days of calories to burn through…which often changed my mind about eating pizza because unless it’s some DAMN good stuff, no pizza is worth 2 days of working out.  😛

When I started thinking like that, that’s when I could see a major change in my weight loss pattern.  It was fairly consistent from 340 all the way down to 280…almost clockwork like.  Just about 1 lb a day was melting off as long as I stuck to my excercise and didn’t stray from eating good foods.  At 280 I hit a wall.  It took me almost a month to start loosing weight again.  I don’t know what the wall was…I was doing all the same things…there was some medical issues going on around the same time frame that I’m guessing was contributing to it but it never stopped me from doing anything so I don’t know…my body just had a stubborn spot I guess.

So the man in the mirror no longer matches the man I see in my head.  Not even close.  When I make a facial expression and I catch a glimps of myself in a mirror doing it, I don’t look at all like I imagine I do…and it’s throwing me for quite a loop.  I feel akward and not myself…which is ok because I wasn’t happy with myself before so I should be ok with not feeling like myself…but I’m kinda uneasy.

I should feel confident and victorious.  I thought the moment I hit 265 that I would scream out in celebration enough to wake the house…but what really happened was I smiled for a minute and caught a glimpse of that smile in the mirror and it looked like someone else was smiling…and it freaked me out a little.

I may have the fortitude, willpower, strength of character…the “whatever” it is to have accomplished this amazing feat of loosing all that weight naturally with no surgery or weight lose pills or crap like that.  I’m so proud of that.  However…what I realize is that I did not gain any confidence.  I think everyone still looks at me and is thinking “what a fatty”.  I suppose I need to give it time to grow…time for my minds image to catch up with my physical one…but I’m giving as honest of an accounting of what I’m thinking and feeling as I can.

So now I adjust to my new lifestyle.  It wasn’t a diet, it was a life changing and life saving adjustment in my eating habits.  It wasn’t just working out to lose weight, it’s changing myself to being an active person vs a sedentary one.  I hope someday I’ll loose the desire to snack…so far that’s been the hardest thing to swallow so to speak is that I miss binge snacking.  :-\

And also…now it’s time to start finding that confidence.  That’s going to be a longer more difficult journey…but it’s one I need to make for the EXACT same reasons I did the weight loss and why I’m doing the grappling tourneyment.  To give my children the best possible example to follow that I can…and to give them the hardest, most difficult target for them to one day surpass.

I know I said it on FB…but I’m going to say it again here…thank you to everyone who gave me even the smallest amount of encouragment.  I used it all.  You guys are all my heroes.

A special thanks goes out to:

  • My wife – she has been putting my with my determination which at times is a bitter pill to take.  I’m stubborn, thick headed, and think I know better than I do.  She weathered the storm and kept beating it into my head about eating better and watching my calories…maybe even creating a monster in the process so to speak…but I couldn’t have done it without her.  She’s very much the backbone to our family and she’s a pillar to my success.  I could not be who I am now without her.
  • My kids – nothing has inspired me to get off my butt and lose the weight until my kiddos came into my life and were there with me everyday…and I realized that I couldn’t keep up with them and I had to do something about it.  Watching how much they respond and copy the things I do is all it took to inspire me to be better so that they’ll want to be better.  I know I’m their image for how to be a man, I see them copy the things I do all the time…I’m 100% determined to be the best image I can be for them.
  • Sifu – Through my grumpiness, whining, injuries, constant questions, and general craziness…Sifu has nudged me, pushed me, and sometimes shoved me to being a better person.  He’s one of the templates I use to figure out what I want to be for my kids…he has become another pillar to my success and I will give credit where it’s due.  I never thought in a million years I’d actually get to 265…but he never had a doubt.  I’ve come to enjoy and rely on his wisdom, advice, and humor in more than just kungfu and look forward to whenever I’m heading out to his training compound.  You are a big part of what helped turn my life around.
  • The Kungfu Crew – Gabe, Tim, Jeff, Nikki, Leo, Wolf, Lexi, Vlad, Olga, Steve, Ian, Andy, Carl, the list could go on and on and on…you guys are all the best…I know I am a pain in the butt to deal with sometimes…thank you all so much for pushing me to be better, for challanging me to reach a little further, and giving me such a huge wide range of champion attitudes to draw knowledge and advice from.  You guys are an amazing group of friends and I will bust my ass to be as great of a training partner to you all as you’ve been to me…I will work to be that inspiration in you as well.

Ok…now to train for November and kick some ass!  🙂

 

That was a long journey…

A moment of captured soul

This morning I was listening to whatever happened to randomly pop up on my master favorites list.  Just a small list of 1500 songs or so that I’ve liked over the years.

Poison’s Ball and Chain came up.  Now this song isn’t on my favorites list because of it’s masterful level of guitar playing or it’s amazing level of song construction.  I mean everyone knows it…this is a filler song.  Poison did not sit around for months thinking that one up.  It is however a great song to use for improving guitar skills…lots of cool good practice riffs in there.

No…this song is on my favorites list because before the song even really starts you hear what sounds like the band warming up.  It could all be part of the song or someone could have just flipped on the recording equipment as the band was getting ready to go…I don’t know the true story behind the recording…but somewhere around 28-29 seconds into the recording you can hear a piece of the guitarists soul…just for a split second.  I don’t know if he meant it to happen or if it just accidentally slipped out, but everytime I hear him do that walk down from that riff…I get a picture of him in my head and I imagine the look on his face is so intense right there.  Every damn time I hear that…I think of that same thing.  It’s not complex, it’s not long, it’s not some thrashing thing…just something quick, pure, an simple.  That’s what it’s there.

A moment of captured soul

Beast

The title says it all…it’s the name (well, not the exact name…no need to make hacking me any easier on someone…hehehe) I’ve given to my monster machine that I built for pretty close to the same amount I spent on my previous gaming rig.  The difference, the first one I had built for me at a Computer Stop store near where I work…the other is one I built myself about 6 years later.

The store built one was running an Intel I5 (can’t remember the speed) with 8 gigs of ram and a Nvidia 970 GTX with a 1 gig of ram on it.  It was a pretty darn fine gaming rig 6 years ago…and is “ok” for today’s games.  I added on an SSD drive which kept it limping along and have since given it to one of my kids for their first gaming rig.

The one I’ve recently built is only rivaled by Terry Cruz’s monster machine…which only beats mine because he’s doing dual SLI GTX 1080’s…lucky bugger.  😉  I’m now running an Intel I7-6700 unlocked, 32 gigs of ram, GTX 1070 with 4 gigs of ram on it, SSD hard drive for the games and system drive…and it’s also running 5 – 1 TB drives setup in a RAID 5 drive array for storing our family media.

I’m very…let me stress that a little better…VERY happy with this new machine…it is a beast.  It has varying speed control on all it’s fans…and it’s got 11 of them.  I decided to stick with fans instead of liquid cooling because all the research I did said that the things I was running just didn’t produce enough heat to warrent liquid cooling…seemed to me the ones that did it were just doing it for bragging rights and for me…it seems like mixing luquids with electronics is always a bad idea in general, so I stuck with what I knew…not at all sad for doing it.

I “accidentally” bought a case that was a “bit” bigger than I was expecting.  You know, one of those accidents that happen when you just look at a picture and totally ignore the listed dimensions.  Yeah…so, long story short…I got this monstersly HUGE Cosmos II case from Casemasters.  Without hesitation I can tell you it’s the biggest damn case I’ve ever seen…my first reaction was “where the hell am I going to put it?”…after having it for about a month now, I’m so happy I got this case.  It was so easy to install everything into because of the large amount of space.  It’s so well designed for air flow and cable routing…really I could go on for probably a whole page on what I liked about working on that case…and it’s whisper quiet while running (well until I turn the fans on high)…really if you have a little extra to spend on your build…buy this damn case!  😉

This being the first PC I’ve built in more than 10 years…things have changed a bit.  Cabling is so much easier now…OMG what the hell were we thinking 10 years ago.  In general everything about putting a system together is so much smoother now than it used to be…except for getting the SATA connections in…but they could have been due to me adding the drives in as my last step.  I LOVE how the CPU doesn’t have pins on it anymore…the ram went in so nicely…the CPU fan was pretty easy to do once I figured out the fan’s mechism…yeah, it just went so smooth.  I turned it on and Beast came to life with no issues at all…and has blown me away with it’s performance.

I decided to look into how it compared up to the beasty machine I have at work for doing builds.  Well that machine is about 4 years old now running dual Xeon E5 6 core procs with 32 gigs of ram and an SSD drive specifically setup to deal with building code fast.  It’s always been the fastiest machine I’ve ever used…until now.  My new gaming rig is blowing it away in every category.  I’d love to bring it to work and have them do building side by side to see which one does better, but it’s probably not a good idea to bring my personal machine into work just for something like that.  😉  I think the build machine would still win just because it has 12 cores cranking away at building while my gaming rig would only have 4 cores…even though they are going twice the speed, it just wouldn’t be enough to overtake 12 cores.  Be a fun race tho for geek like me.  😉

So to wrap up…I’m loving the I7-6700, loving the GTX 1070, loving the Casemaster Cosmos II…really glad I decided to build a machine again.  I’ve thrown every hard hitting graphical game I have at it set at the highest settings and I’ve never experienced a bit of lag anywhere.  So awesome.  🙂

Beast

So tired!

Hello all,

It’s been a while since I’ve posted anything…nearly 2 months I think.  It’s the usual stuff happening, I get some down time, I start writing stuff, then I get busy again and the stuff I’ve been writing gets back burnered.

Ah well…it happens.  I’ll be making an effort to keep coming back to it though instead of just quitting…it’ll be useful to someone eventually.

But today is not about learning new coding stuff…today I’m going to post about my fitness journey.

As I’ve said many times since I started the blog, I’ve been in training to do a grappling tourneyment in Novemenber 2016.  That’s only 4 months away at the time of this post.  When I decided to do this compitition I was at about 340lbs.  I’m now at 280.  I’ve been at 280 now for the last 2 weeks and I can’t seem to make myself get any lower lately.

Hitting a plateau in weight loss sucks.  It’s so demoralizing when you’ve been doing well for a few months, then it just hits a wall.  To add on top of that I’ve been training injured in my jaw, arms (it was just the right one, but now the left one is starting to have the same problems), my back, and other things I don’t want to mention.  Let it just suffice to say I’ve been in some degree of pain everyday for the last 3 months solid…now that’s demoralizing.

Probably for the last month, I’ve been dead tired all the time as well.  Sure I can still manage to summon up the will to push myself into activity, but it’s getting more difficult to do as each day passes.  I’ve even heard thoughts echo’ing in my head asking if it’s all worth it.

Well hell yeah it’s still worth it, but honestly I’ve never wanted something to be over so much in my life.  I’m in a constant state of stress and it’s exhausting.  I’m worried that I’m not getting better fast enough, that I get my ass handed to me by everyone else in grappling class lately, that my weight loss has slowed significantly, that I’m constantly injured and when I start getting close to being healed up I get reinjured…then add this being tired all the time on top of all that…it’s not a good receipe for a healthy Toffer…well…it sort of is, I mean I’m in better shape than I had been in 20 years, but that’s not the sort of health I’m talking about.  It’s stress health and the weight of it is starting to get to me.

I just need to stay focused on November, all the stress will wash away when I have my first fight in my tourney…I had been thinking I’d be sad if I didn’t win…but now I don’t think that’ll be the case.  Honestly at this point, win or lose I think I’ll just be celebrating that I had made it there still alive.

So tired!

Addicted to Eating

Hey all…still here and still thinking about things to post.  I have code experiments on the back burner waiting for work to get a little less busy so I can polish up the examples…but the bulk of my spare time goes towards working out these days.

I don’t mean I’m spending hours on end working out (well…maybe on grappling days)…but the whole process of working out really takes any extra energy out of me that I previously was using to do my coding posts…so, I’ll get around to them…but I’m trying to keep in the habit of posting something at least once a week…so this week it’ll be about my struggle with eating.

I can tell you without hesitation…of all the addictive things I’ve done in my lifetime, nothing compares to the pull eating has over me.  Time and again it has won the battle for dominance over my body…as I’m sure one day it will again defeat my resolve and determination.  If I don’t constantly watch what I’m doing I can and will mindlessly eat my way through any amount of food…entire family sized pizza’s…bags of chips…tubs of ice cream…all have fallen victim to my binges.

I’m a good streak right now.  I have good support to lean on in weak moments.  I have a powerful goal that helps keep me focused.  Even through all that the demon claws at me begging me to fill my face with endless calories.  But November is only 6-7 months away and my goal of getting to below 300 before competing is within my reach…actually getting below 280, which is what I weighed when I graduated high school, is within my reach.  That would be very weird to be in better shape at 43 than I was at 18…a good weird.

As long time readers will know I attribute most of my current weight loss to my working out.  I put a lot of effort into it.  I burn through a ton of calories.  I’m very serious about getting something out of it everytime I put effort into working out, because I HATE HATE HATE doing it…so I better get something out of it for my trouble.

What I had been doing is just eating normally while working out like crazy…and that worked for a while.  I started to stall in my weight loss though so I then cut out eating fast food.  That made a huge difference.  Apprently that stuff is bad for you, who knew.

Well…that only worked for so long as well and I began to stall once again…so now I’ve added cutting back the amount I’m eating into the whole equation…and I’ve again started to drop pounds…but the eating addiction has started rearing it’s ugly head.  Hungry or not I often think of snacking.  😦

It’s taking a lot more determination than I thought it would to resist eating…it’s even harder to do then not listen to MJK music.  Every extra second I have my mind drifts to thinking about stuffing something in my face.  Ugh…will I ever be rid of this addiction.  My whole life it’s been a monkey on my back.  I’d seriously consider having the procedure done if they knew a place in my brain to zap with a sodering iron or something to kill the eating addiction section of the brain…hmmm, maybe that’s how zombies are made.  😉

Anyway, enough complaining for now…as of the moment I’m winning the eatting addiction battle and I’m at 304 pounds (starting from an estimated 360).  That’s victory enough for today.  Hope this has inspired someone to hold the demon at bay!

Addicted to Eating

I am a MACHINE!

No intro…getting right into the post…oh crap, I guess that was an intro just now…  😛

So I’ve been told and have read things over the years about how to stay in shape.  I’m sure you all know it boils down to exercising and eating right.  If you don’t…let me save you some time…IT ALL BOILS DOWN TO EXERCISING AND EATING RIGHT.  There, now you know the secret.

Now that I’m drinking the “get in shape” coolaid so to speak, I can notice that my body is responding.  I’ve been feeling stronger…my stamina is getting better…I’m loosing weight…so I’d guess that means my body is fixing the damage.  However I still look old.

AFAIK, when you’re working out…you are actually causing damage to your muscles which is what causes them to grow back stronger and more resistent to being damaged again…which means that your body is generating new tissue and cells.

Aging is the process of your cells degrading over time as they’re being replaced…kinda like a copy of a copy of a copy of a cpy of a cpy of a cpy of a cp of a cp of a cp (see what I did there?)

One of my questions is if you body is creating new cells for your muscles…those are brand new…shouldn’t they be starting out at the “original” point instead of the “copy of a copy of a copy” point?

And that just leads me to another question about skin…as I’m loosing weight I can see more and more flab, which is skin that’s been stretched out too far and won’t shrink…what would happen if I just had all the flab cut off and let the skin grow back on it’s own (if that was even possible without dying).  Would it grow back as the stretched skin or would it came back as the “original”?

I’ve always have had the point of view that my body is just a machine…and it reflects how well I’ve taken care of it.  I would say it’s just like a car in that if you put crappy fuel in and never get it serviced…the car would die before it’s time…however in that analogy if you start putting in good fuel and servicing the car…it doesn’t magically heal that car from all wounds…the damage is done.  From what I’ve noticed in myself, that’s not entirely so for people when they let themselves go and start getting back into good health.  The damage may be done…but we heal that damage to a degree, but you just cannot heal the damage that aging does.  It’s like there some master blueprint of what it takes to make the components in your body and it’s stored somewhere out in the open where the blueprint continuously degrades from being eroded by weather…and there’s nothing that can be done about it.  Man that pisses me off!  The idea that I’m just going to keep withering away no matter how much time and effort I put into stopping it…it’s very frustrating.

But then I think of the inevitable zombie apocolypse that’s sure to take place any day now and I know I’ll be put all this working out and getting into shape to good use.  😉

Anyway…just some food for thought.  Feel free to comment or not.  Enjoy.  🙂

I am a MACHINE!

WPF using BackgroundWorker vs using Task

Today I’m expanding on the ExampleAppinator post that I made last week which will be the foundation to my examples going forward.  In this I’m going to show an example that simply outputs the contents of the KitchenSink tables into grids…1 set using BackgroundWorker to create threads for doing the fetching of data, the other set is using a Task.

I’ll post the ending source code to the WPF example app at the end of this post.

The first thing I noticed when I put this together is that when there wasn’t a lot of data in the table, it really took little to no time to ever get anything out of the database so it was nealry impossible to see any difference in BackgroundWorker vs Task…which is what lead to me creating KitchenSinkClogger in the ExampleAppinator post.  I created that and let it run for the weekend…it filled up my database with about 250000 records.  Perfect, now I have some meat to sink my teeth into.

Now when I launched the test WPF app, I ran into some real perf problems.  At this stage of the test I had 12 DataGrid’s being loaded up simultaniously, 6 using BackgroundWorker threads, 6 using Task threads.  When I launched it, for about 5 solid minutes nothing happened but churning in the debugger.  I paused it in the debugger a couple times just to verify that there were worker threads churning in the background…and as far as I can tell, none of them should have been on the UI thread so the UI should have never locked up…I’m a bit confused by that one.

From here I had a thought that maybe the app was becoming unresponsive because I was trying to load up 12 DataGrid’s with 250000 records each and it was a memory issues…so I decided to add pagers to my DataGrids…and since that’s a total pain in the backside with normal built in WPF controls I decided to switch over to using Telerik controls at this point since they have a ready made RadDataPager object I could use.  About 10 minutes later…everything was switched over to RadBusyIndicator’s and RadGridView’s with a RadDataPager in place and as I tested out each individual grid they were all working smooth…until…I turned them all on to load at the same time again.  Again the app was brought down to it’s knees in perf.

So this is where I’m at right now as of 5/11/2016.  I think my next move is to make a post on the Telerik forums now that I’m using their controls and see if I get lucky with an answer on how to make my little test more performant…but in all honesty I don’t think it has anything to do with the controls.  I think it has something to do with the threads…and that I’m obviously attaching to the UI thread somewhere.

Update on 5/17/2016 – I got a reply from Telerik and they weren’t able to help figure out where I’m getting the performance hit…next I’m going to try disabling all the grids but one and see what kind of perf I get there…then start adding them back in one at a time…all the while monitoring threads to see if I can notice anything strange going on.

As always I encourage anyone reading this to leave a comment if you have questions or feedback…I know I don’t know what I’m doing…but I’m totally willing to learn new techniques.  🙂

Update on 5/25/2016 – Yes I know I haven’t posted in about a week…I’ve gotten busy at work again which cuts into my post preparation time so :P.  Quality posts take time to put together…and since mine suck it takes less time…but still a lot of time.

Update on 5/31/2016 – I did some work on this today and started by narrowing down the grids being returned from the database to just one.  I had to kill my database with over 1 million records in it and I’m currently rebuilding it…but at the moment I get about 11k records returned so fast that I can’t even see the Busy Indicator come up…so now I’m going to wait for the database to fill up again so I can see that.  Trying to make sure that each piece is working individually.  Once I can prove that the busy indicator comes up for a BackgroundWorker thread…then I’m going to try returning the same set of information using a Task thread to see if there’s any noticible difference.  Anyway…that’s where I’m at with this for now.  Stay tuned…I’ll get this figured out eventually.

Update on 6/1/2016 – So I got 500k records in my database now and tried the grid using the BackgroundWorker thread again.  Low and behold the Busy Indicator shows up…woohoo.  Now onto seeing if I get the same results using a Task instead.

Update on 6/7/2016 – Today I made some great progress.  I learned what’s really hanging up the BW thread and the Task threads both is that I’m creating a whole bunch of them that are all using the same resources…the network…so there’s a ton of waiting and locking and syncronizing that the OS is doing with the threads and it causes the UI to seem like it’s getting hung up because the system is busy doing all this work sync’ing background threads.  What I learned to do is put a lock on the parent DLL object I have for all my Linq classes and models with each BW thread that I create.  This way I’m managing the sync’ing by forcing all the threads to wait until usage of the parent object free’s up.  The UI displays the Busy Indicator…all the worker threads spin up just fine…and the UI stays responsive.  The 1 down side of this that I noticed is now you have to wait for each table to load once at a time…even though the busy indicator is there and gives a good experience to the user, I feel there could be some more done here to improve the data retrieval experience.  Also I couldn’t retrieve a table with 5 million records.  Got an OOM expcetion thrown from Linq.  Stupid Linq.  😛  So I’m off to learn some data virtualization techniques so I can apply them to my example app and see if I can actually get back to my original theme to this post…which is better?  BW or Task?  Man, this post is crossing lots of different disciplines.  I like it!  Stay tuned!!!  🙂  I’ll be posting an update to the source code once I get the data virtualization part figured out…

MainWindow XAML:

<Window Height="350"
        mc:Ignorable="d"
        Title="MainWindow"
        Width="525"
        x:Class="CSharpWPFAppinator.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:CSharpWPFAppinator"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
    <Grid>
        <TabControl x:Name="KitchenSinkTabControl">
            <TabItem    Header="BW - Engine"
                        x:Name="BWEngineTab" />
            <TabItem    Header="BW - History"
                        x:Name="BWHistoryTab" />
            <TabItem    Header="BW - Lifeform"
                        x:Name="BWLifeformTab" />
            <TabItem    Header="BW - Planet"
                        x:Name="BWPlanetTab" />
            <TabItem    Header="BW - Species"
                        x:Name="BWSpeciesTab" />
            <TabItem    Header="BW - Vehicle"
                        x:Name="BWVehicleTab" />
            <TabItem    Header="Task - Engine"
                        x:Name="TaskEngineTab" />
            <TabItem    Header="Task - History"
                        x:Name="TaskHistoryTab" />
            <TabItem    Header="Task - Lifeform"
                        x:Name="TaskLifeformTab" />
            <TabItem    Header="Task - Planet"
                        x:Name="TaskPlanetTab" />
            <TabItem    Header="Task - Species"
                        x:Name="TaskSpeciesTab" />
            <TabItem    Header="Task - Vehicle"
                        x:Name="TaskVehicleTab" />
        </TabControl>
    </Grid>
</Window>

MainWindow CS Code Behind:

using System.Windows;
using System.Windows.Controls;

namespace CSharpWPFAppinator
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            KitchenSinkDLL.KitchenSinkDLL.ConnectionString = @"Data Source=cmd-roswell;Initial Catalog=KitchenSink;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False";

            foreach(TabItem item in KitchenSinkTabControl.Items)
            {
                switch(item.Name)
                {
                    case "BWEngineTab":
                        BWEngineUserControl bwEngineControl = new BWEngineUserControl();
                        bwEngineControl.RefreshData();
                        item.Content = bwEngineControl;
                        break;
                    case "BWHistoryTab":
                        BWHistoryUserControl bwHistoryControl = new BWHistoryUserControl();
                        bwHistoryControl.RefreshData();
                        item.Content = bwHistoryControl;
                        break;
                    case "BWLifeformTab":
                        BWLifeformUserControl bwLifeformControl = new BWLifeformUserControl();
                        bwLifeformControl.RefreshData();
                        item.Content = bwLifeformControl;
                        break;
                    case "BWPlanetTab":
                        BWPlanetUserControl bwPlanetControl = new BWPlanetUserControl();
                        bwPlanetControl.RefreshData();
                        item.Content = bwPlanetControl;
                        break;
                    case "BWSpeciesTab":
                        BWSpeciesUserControl bwSpeciesControl = new BWSpeciesUserControl();
                        bwSpeciesControl.RefreshData();
                        item.Content = bwSpeciesControl;
                        break;
                    case "BWVehicleTab":
                        BWVehicleUserControl bwVehicleControl = new BWVehicleUserControl();
                        bwVehicleControl.RefreshData();
                        item.Content = bwVehicleControl;
                        break;
                    case "TaskEngineTab":
                        TaskEngineUserControl taskEngineControl = new TaskEngineUserControl();
                        taskEngineControl.RefreshData();
                        item.Content = taskEngineControl;
                        break;
                    case "TaskHistoryTab":
                        TaskHistoryUserControl taskHistoryControl = new TaskHistoryUserControl();
                        taskHistoryControl.RefreshData();
                        item.Content = taskHistoryControl;
                        break;
                    case "TaskLifeformTab":
                        TaskLifeformUserControl taskLifeformControl = new TaskLifeformUserControl();
                        taskLifeformControl.RefreshData();
                        item.Content = taskLifeformControl;
                        break;
                    case "TaskPlanetTab":
                        TaskPlanetUserControl taskPlanetControl = new TaskPlanetUserControl();
                        taskPlanetControl.RefreshData();
                        item.Content = taskPlanetControl;
                        break;
                    case "TaskSpeciesTab":
                        TaskSpeciesUserControl taskSpeciesControl = new TaskSpeciesUserControl();
                        taskSpeciesControl.RefreshData();
                        item.Content = taskSpeciesControl;
                        break;
                    case "TaskVehicleTab":
                        TaskVehicleUserControl taskVehicleControl = new TaskVehicleUserControl();
                        taskVehicleControl.RefreshData();
                        item.Content = taskVehicleControl;
                        break;
                    default:
                        break;
                }
            }
        }
    }
}

BackgroundWorkerUserControl:

using KitchenSinkDLL.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Telerik.Windows.Controls;
using Xceed.Wpf.Toolkit;

namespace CSharpWPFAppinator
{
    public class BackgroundWorkerUserControl<T> : UserControl
    {
        public BackgroundWorkerUserControl()
        {
            BackgroundWorkerGrid = new Grid();
            BackgroundWorkerGrid.ColumnDefinitions.Add(new ColumnDefinition());
            BackgroundWorkerGrid.RowDefinitions.Add(new RowDefinition());
            BackgroundWorkerGrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });

            BackgroundWorkerRadGridView = new RadGridView();
            Grid.SetColumn(BackgroundWorkerRadGridView, 0);
            Grid.SetRow(BackgroundWorkerRadGridView, 0);
            BackgroundWorkerGrid.Children.Add(BackgroundWorkerRadGridView);

            BackgroundWorkerRadDataPager = new RadDataPager();
            BackgroundWorkerRadDataPager.AutoEllipsisMode = AutoEllipsisModes.Both;
            BackgroundWorkerRadDataPager.DisplayMode = PagerDisplayModes.All;
            BackgroundWorkerRadDataPager.NumericButtonCount = 10;
            BackgroundWorkerRadDataPager.PageSize = 40;
            BackgroundWorkerRadDataPager.VerticalAlignment = VerticalAlignment.Bottom;
            BackgroundWorkerRadDataPager.Source = BackgroundWorkerRadGridView.Items;
            Grid.SetColumn(BackgroundWorkerRadDataPager, 0);
            Grid.SetRow(BackgroundWorkerRadDataPager, 1);
            BackgroundWorkerGrid.Children.Add(BackgroundWorkerRadDataPager);

            BackgroundWorkerRadBusyIndicator = new RadBusyIndicator();
            BackgroundWorkerRadBusyIndicator.Content = BackgroundWorkerGrid;

            Content = BackgroundWorkerRadBusyIndicator;

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            BackgroundWorker = new BackgroundWorker();
            BackgroundWorker.DoWork += BackgroundWorkerDoWork;
            BackgroundWorker.RunWorkerCompleted += BackgroundWorkerCompleted;
        }

        private BackgroundWorker BackgroundWorker { get; set; }

        private Grid BackgroundWorkerGrid { get; set; }

        private RadBusyIndicator BackgroundWorkerRadBusyIndicator { get; set; }

        private RadDataPager BackgroundWorkerRadDataPager { get; set; }

        private RadGridView BackgroundWorkerRadGridView { get; set; }

        private DateTime LastHistoryUpdate { get; set; }

        private void BackgroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Dispatcher.BeginInvoke(new Action<IEnumerable<T>>(RefreshBackgroundWorkerDataGrid), e.Result);
        }

        private void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = KitchenSinkDLL.KitchenSinkDLL.ReadTable<T>();
        }

        private void RefreshBackgroundWorkerDataGrid(IEnumerable<T> engines)
        {
            BackgroundWorkerRadGridView.ItemsSource = null;

            if (engines != null)
            {
                LastHistoryUpdate = HistoryModel.ReadLastHistoryUpdate();
                BackgroundWorkerRadGridView.ItemsSource = engines;
            }

            BackgroundWorkerRadBusyIndicator.IsBusy = false;
        }

        public void RefreshData()
        {
            if (!BackgroundWorker.IsBusy)
            {
                DateTime currentLastHistoryUpdate = HistoryModel.ReadLastHistoryUpdate();

                if (currentLastHistoryUpdate > LastHistoryUpdate)
                {
                    BackgroundWorkerRadBusyIndicator.IsBusy = true;
                    BackgroundWorker.RunWorkerAsync();
                }
            }
        }
    }
}

TaskUserControl:

using KitchenSinkDLL.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Telerik.Windows.Controls;
using Xceed.Wpf.Toolkit;

namespace CSharpWPFAppinator
{
    public class TaskUserControl<T> : UserControl
    {
        public TaskUserControl()
        {
            TaskGrid = new Grid();
            TaskGrid.ColumnDefinitions.Add(new ColumnDefinition());
            TaskGrid.RowDefinitions.Add(new RowDefinition());
            TaskGrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });

            TaskRadGridView = new RadGridView();
            Grid.SetColumn(TaskRadGridView, 0);
            Grid.SetRow(TaskRadGridView, 0);
            TaskGrid.Children.Add(TaskRadGridView);

            TaskRadDataPager = new RadDataPager();
            TaskRadDataPager.AutoEllipsisMode = AutoEllipsisModes.Both;
            TaskRadDataPager.DisplayMode = PagerDisplayModes.All;
            TaskRadDataPager.NumericButtonCount = 10;
            TaskRadDataPager.PageSize = 40;
            TaskRadDataPager.VerticalAlignment = VerticalAlignment.Bottom;
            TaskRadDataPager.Source = TaskRadGridView.Items;
            Grid.SetColumn(TaskRadDataPager, 0);
            Grid.SetRow(TaskRadDataPager, 1);
            TaskGrid.Children.Add(TaskRadDataPager);

            TaskRadBusyIndicator = new RadBusyIndicator();
            TaskRadBusyIndicator.Content = TaskGrid;

            Content = TaskRadBusyIndicator;

            if (DesignerProperties.GetIsInDesignMode(this))
                return;
        }

        private Grid TaskGrid { get; set; }

        private RadBusyIndicator TaskRadBusyIndicator { get; set; }

        private RadDataPager TaskRadDataPager { get; set; }

        private RadGridView TaskRadGridView { get; set; }

        private DateTime LastHistoryUpdate { get; set; }

        private IEnumerable<T> Records { get; set; }

        private void FetchDataForControl()
        {
            Records = KitchenSinkDLL.KitchenSinkDLL.ReadTable<T>();
        }

        private void RefreshTaskDataGrid()
        {
            TaskRadGridView.ItemsSource = null;

            if (Records != null)
            {
                LastHistoryUpdate = HistoryModel.ReadLastHistoryUpdate();
                TaskRadGridView.ItemsSource = Records;
            }
        }

        public async Task RefreshData()
        {
            TaskRadBusyIndicator.IsBusy = true;

            await Task.Run(() =>
            {
                DateTime currentLastHistoryUpdate = HistoryModel.ReadLastHistoryUpdate();

                if (currentLastHistoryUpdate > LastHistoryUpdate)
                {
                    FetchDataForControl();
                }
            });

            RefreshTaskDataGrid();
            TaskRadBusyIndicator.IsBusy = false;
        }
    }
}

BWEngineUserControl XAML:

<UserControl    d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d"
                x:Class="CSharpWPFAppinator.BWEngineUserControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:local="clr-namespace:CSharpWPFAppinator"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
    <Grid x:Name="BWEngineGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
</UserControl>

BWEngineUserControl CS Code Behind:

using KitchenSinkDLL.Models;
using System.ComponentModel;
using System.Windows.Controls;

namespace CSharpWPFAppinator
{
    /// <summary>
    /// Interaction logic for BWEngineUserControl.xaml
    /// </summary>
    public partial class BWEngineUserControl : UserControl
    {
        public BWEngineUserControl()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            EngineUserControl = new BackgroundWorkerUserControl<EngineModel>();
            Grid.SetColumn(EngineUserControl, 0);
            Grid.SetRow(EngineUserControl, 0);
            BWEngineGrid.Children.Add(EngineUserControl);
        }

        private BackgroundWorkerUserControl<EngineModel> EngineUserControl { get; set; }

        public void RefreshData()
        {
            EngineUserControl.RefreshData();
        }
    }
}

TaskEngineUserControl XAML:

<UserControl    d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d"
                x:Class="CSharpWPFAppinator.TaskEngineUserControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:local="clr-namespace:CSharpWPFAppinator"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
    <Grid x:Name="TaskEngineGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
</UserControl>

TaskEngineUserControl CS Code Behind:

using KitchenSinkDLL.Models;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace CSharpWPFAppinator
{
    /// <summary>
    /// Interaction logic for TaskEngineUserControl.xaml
    /// </summary>
    public partial class TaskEngineUserControl : UserControl
    {
        public TaskEngineUserControl()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            EngineUserControl = new TaskUserControl<EngineModel>();
            Grid.SetColumn(EngineUserControl, 0);
            Grid.SetRow(EngineUserControl, 0);
            TaskEngineGrid.Children.Add(EngineUserControl);
        }

        private TaskUserControl<EngineModel> EngineUserControl { get; set; }

        public async Task RefreshData()
        {
            await EngineUserControl.RefreshData();
        }
    }
}

BWHistoryUserControl XAML:

<UserControl    d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d"
                x:Class="CSharpWPFAppinator.BWHistoryUserControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:local="clr-namespace:CSharpWPFAppinator"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
    <Grid x:Name="BWHistoryGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
</UserControl>

BWHistoryUserControl CS Code Behind:

using KitchenSinkDLL.Models;
using System.ComponentModel;
using System.Windows.Controls;

namespace CSharpWPFAppinator
{
    /// <summary>
    /// Interaction logic for BWHistoryUserControl.xaml
    /// </summary>
    public partial class BWHistoryUserControl : UserControl
    {
        public BWHistoryUserControl()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            HistoryUserControl = new BackgroundWorkerUserControl<HistoryModel>();
            Grid.SetColumn(HistoryUserControl, 0);
            Grid.SetRow(HistoryUserControl, 0);
            BWHistoryGrid.Children.Add(HistoryUserControl);
        }

        private BackgroundWorkerUserControl<HistoryModel> HistoryUserControl { get; set; }

        public void RefreshData()
        {
            HistoryUserControl.RefreshData();
        }
    }
}

TaskHistoryUserControl XAML:

<UserControl    d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d"
                x:Class="CSharpWPFAppinator.TaskHistoryUserControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:local="clr-namespace:CSharpWPFAppinator"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
    <Grid x:Name="TaskHistoryGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
</UserControl>

TaskHistoryUserControl CS Code Behind:

using KitchenSinkDLL.Models;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace CSharpWPFAppinator
{
    /// <summary>
    /// Interaction logic for TaskHistoryUserControl.xaml
    /// </summary>
    public partial class TaskHistoryUserControl : UserControl
    {
        public TaskHistoryUserControl()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            HistoryUserControl = new TaskUserControl<HistoryModel>();
            Grid.SetColumn(HistoryUserControl, 0);
            Grid.SetRow(HistoryUserControl, 0);
            TaskHistoryGrid.Children.Add(HistoryUserControl);
        }

        private TaskUserControl<HistoryModel> HistoryUserControl { get; set; }

        public async Task RefreshData()
        {
            await HistoryUserControl.RefreshData();
        }
    }
}

BWLifeformUserControl XAML:

<UserControl    d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d"
                x:Class="CSharpWPFAppinator.BWLifeformUserControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:local="clr-namespace:CSharpWPFAppinator"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
    <Grid x:Name="BWLifeformGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
</UserControl>

BWLifeformUserControl CS Code Behind:

using KitchenSinkDLL.Models;
using System.ComponentModel;
using System.Windows.Controls;

namespace CSharpWPFAppinator
{
    /// <summary>
    /// Interaction logic for BWLifeformUserControl.xaml
    /// </summary>
    public partial class BWLifeformUserControl : UserControl
    {
        public BWLifeformUserControl()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            LifeformUserControl = new BackgroundWorkerUserControl<LifeformModel>();
            Grid.SetColumn(LifeformUserControl, 0);
            Grid.SetRow(LifeformUserControl, 0);
            BWLifeformGrid.Children.Add(LifeformUserControl);
        }

        private BackgroundWorkerUserControl<LifeformModel> LifeformUserControl { get; set; }

        public void RefreshData()
        {
            LifeformUserControl.RefreshData();
        }
    }
}

TaskLifeformUserControl XAML:

<UserControl    d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d"
                x:Class="CSharpWPFAppinator.TaskLifeformUserControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:local="clr-namespace:CSharpWPFAppinator"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
    <Grid x:Name="TaskLifeformGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
</UserControl>

TaskLifeformUserControl CS Code Behind:

using KitchenSinkDLL.Models;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace CSharpWPFAppinator
{
    /// <summary>
    /// Interaction logic for TaskLifeformUserControl.xaml
    /// </summary>
    public partial class TaskLifeformUserControl : UserControl
    {
        public TaskLifeformUserControl()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            LifeformUserControl = new TaskUserControl<LifeformModel>();
            Grid.SetColumn(LifeformUserControl, 0);
            Grid.SetRow(LifeformUserControl, 0);
            TaskLifeformGrid.Children.Add(LifeformUserControl);
        }

        private TaskUserControl<LifeformModel> LifeformUserControl { get; set; }

        public async Task RefreshData()
        {
            await LifeformUserControl.RefreshData();
        }
    }
}

BWPlanetUserControl XAML:

<UserControl    d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d"
                x:Class="CSharpWPFAppinator.BWPlanetUserControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:local="clr-namespace:CSharpWPFAppinator"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
    <Grid x:Name="BWPlanetGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
</UserControl>

BWPlanetUserControl CS Code Behind:

using KitchenSinkDLL.Models;
using System.ComponentModel;
using System.Windows.Controls;

namespace CSharpWPFAppinator
{
    /// <summary>
    /// Interaction logic for BWPlanetUserControl.xaml
    /// </summary>
    public partial class BWPlanetUserControl : UserControl
    {
        public BWPlanetUserControl()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            PlanetUserControl = new BackgroundWorkerUserControl<PlanetModel>();
            Grid.SetColumn(PlanetUserControl, 0);
            Grid.SetRow(PlanetUserControl, 0);
            BWPlanetGrid.Children.Add(PlanetUserControl);
        }

        private BackgroundWorkerUserControl<PlanetModel> PlanetUserControl { get; set; }

        public void RefreshData()
        {
            PlanetUserControl.RefreshData();
        }
    }
}

TaskPlanetUserControl XAML:

<UserControl    d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d"
                x:Class="CSharpWPFAppinator.TaskPlanetUserControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:local="clr-namespace:CSharpWPFAppinator"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
    <Grid x:Name="TaskPlanetGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
</UserControl>

TaskPlanetUserControl CS Code Behind:

using KitchenSinkDLL.Models;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace CSharpWPFAppinator
{
    /// <summary>
    /// Interaction logic for TaskPlanetUserControl.xaml
    /// </summary>
    public partial class TaskPlanetUserControl : UserControl
    {
        public TaskPlanetUserControl()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            PlanetUserControl = new TaskUserControl<PlanetModel>();
            Grid.SetColumn(PlanetUserControl, 0);
            Grid.SetRow(PlanetUserControl, 0);
            TaskPlanetGrid.Children.Add(PlanetUserControl);
        }

        private TaskUserControl<PlanetModel> PlanetUserControl { get; set; }

        public async Task RefreshData()
        {
            await PlanetUserControl.RefreshData();
        }
    }
}

BWSpeciesUserControl XAML:

<UserControl    d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d"
                x:Class="CSharpWPFAppinator.BWSpeciesUserControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:local="clr-namespace:CSharpWPFAppinator"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
    <Grid x:Name="BWSpeciesGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
</UserControl>

BWSpeciesUserControl CS Code Behind:

using KitchenSinkDLL.Models;
using System.ComponentModel;
using System.Windows.Controls;

namespace CSharpWPFAppinator
{
    /// <summary>
    /// Interaction logic for BWSpeciesUserControl.xaml
    /// </summary>
    public partial class BWSpeciesUserControl : UserControl
    {
        public BWSpeciesUserControl()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            SpeciesUserControl = new BackgroundWorkerUserControl<SpeciesModel>();
            Grid.SetColumn(SpeciesUserControl, 0);
            Grid.SetRow(SpeciesUserControl, 0);
            BWSpeciesGrid.Children.Add(SpeciesUserControl);
        }

        private BackgroundWorkerUserControl<SpeciesModel> SpeciesUserControl { get; set; }

        public void RefreshData()
        {
            SpeciesUserControl.RefreshData();
        }
    }
}

TaskSpeciesUserControl XAML:

<UserControl    d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d"
                x:Class="CSharpWPFAppinator.TaskSpeciesUserControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:local="clr-namespace:CSharpWPFAppinator"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
    <Grid x:Name="TaskSpeciesGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
</UserControl>

TaskSpeicesUserControl CS Code Behind:

using KitchenSinkDLL.Models;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace CSharpWPFAppinator
{
    /// <summary>
    /// Interaction logic for TaskSpeciesUserControl.xaml
    /// </summary>
    public partial class TaskSpeciesUserControl : UserControl
    {
        public TaskSpeciesUserControl()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            SpeciesUserControl = new TaskUserControl<SpeciesModel>();
            Grid.SetColumn(SpeciesUserControl, 0);
            Grid.SetRow(SpeciesUserControl, 0);
            TaskSpeciesGrid.Children.Add(SpeciesUserControl);
        }

        private TaskUserControl<SpeciesModel> SpeciesUserControl { get; set; }

        public async Task RefreshData()
        {
            await SpeciesUserControl.RefreshData();
        }
    }
}

BWVehicleUserControl XAML:

<UserControl    d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d"
                x:Class="CSharpWPFAppinator.BWVehicleUserControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:local="clr-namespace:CSharpWPFAppinator"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
    <Grid x:Name="BWVehicleGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
</UserControl>

BWVehicleUserControl CS Code Behind:

using KitchenSinkDLL.Models;
using System.ComponentModel;
using System.Windows.Controls;

namespace CSharpWPFAppinator
{
    /// <summary>
    /// Interaction logic for BWVehicleUserControl.xaml
    /// </summary>
    public partial class BWVehicleUserControl : UserControl
    {
        public BWVehicleUserControl()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            VehicleUserControl = new BackgroundWorkerUserControl<VehicleModel>();
            Grid.SetColumn(VehicleUserControl, 0);
            Grid.SetRow(VehicleUserControl, 0);
            BWVehicleGrid.Children.Add(VehicleUserControl);
        }

        private BackgroundWorkerUserControl<VehicleModel> VehicleUserControl { get; set; }

        public void RefreshData()
        {
            VehicleUserControl.RefreshData();
        }
    }
}

TaskVehicleUserControl XAML:

<UserControl    d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d"
                x:Class="CSharpWPFAppinator.TaskVehicleUserControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:local="clr-namespace:CSharpWPFAppinator"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
    <Grid x:Name="TaskVehicleGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
    </Grid>
</UserControl>

TaskVehicleUserControl CS Code Behind:

using KitchenSinkDLL.Models;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace CSharpWPFAppinator
{
    /// <summary>
    /// Interaction logic for TaskVehicleUserControl.xaml
    /// </summary>
    public partial class TaskVehicleUserControl : UserControl
    {
        public TaskVehicleUserControl()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            VehicleUserControl = new TaskUserControl<VehicleModel>();
            Grid.SetColumn(VehicleUserControl, 0);
            Grid.SetRow(VehicleUserControl, 0);
            TaskVehicleGrid.Children.Add(VehicleUserControl);
        }

        private TaskUserControl<VehicleModel> VehicleUserControl { get; set; }

        public async Task RefreshData()
        {
            await VehicleUserControl.RefreshData();
        }
    }
}
WPF using BackgroundWorker vs using Task