Introduction and a dumb question

Introduction and a dumb question

Old forum URL: forums.lhotka.net/forums/t/4233.aspx


OldBob-Sco posted on Thursday, January 24, 2008

Hi everyone

First I think an introduction is in order. This is my first post (of which I hope there will be many) on the forum, so I think I'd better say hi to you all (especially Rocky for making my brain hurt).

Bit of a background. I've been a developer for too many years to remember, and concentrated on another M$ product which will remain nameless, but have been moving gradually over to C#, and no doubt like a few people here, started writing C# apps the hard way. I came across a review of Rockys book (Expert C# 2005 Business Objects) which sang it's praises, and as I'm familiar with frameworks (in another life) I thought it was probably the ideal option for me to get to grips with C# in a sort of "serious" way instead of writing small self contained apps. So, thanks Rocky, I've read the book, and now re-reading it. I confess I don't fully understand everything, but I see where you're coming from.

I've started on my first app using the framework and hit a little thorn in my side. Unfortunately, I'm not the kind of guy who hits a problem and then works around it. I will spend hours banging my head against the wall until I fully understand the problem and why .. and then working around it.

The little thorn is the StatusBusy class. When Logging on the "Verifying credentials..." does not appear in the status bar. I have checked and rechecked attributes etc, and they match ProjectTracker so for the life of me I cannot figure it out. Placing MainForm.Instance.Text = statusText; in the same method will change the caption on the main form, but the text will not appear in the statusStrip even when stepping through the code.

Did anyone else experience this? Have I missed the obvious.

Thanks in advance...

ajj3085 replied on Friday, January 25, 2008

Hello,

I think the problem with StatusBusy is that it tries to update the label, but because the data access is also running on the UI thread, you don't see anything get updated.  The same applies to stepping, because the UI thread is blocked until you hit the step key. 

I think you're better off ditching the StatusBusy idea, and instead using a BackgroundWorker component.  You basically update the UI status to read Busy or whatever you need, then tell the worker component to start.  Your BO's Fetch will then run on the background thread, in the DoWork event handler.  Your RunWorkerCompleted handler will then get the object and reset the status back.

HTH
Andy

mr_lasseter replied on Friday, January 25, 2008

You could just call Invalidate on the status label after you change the text.  This will force the control to redraw itself.

tmg4340 replied on Friday, January 25, 2008

Calling Invalidate() doesn't force an immediate refresh - it just puts a refresh message in the message loop.  If the data-retrieval work is being done on the UI thread, as Andy suggested, then that is blocking the UI thread from doing much of anything else.  So the app has to wait for the data-retrieval process to get done before doing anything else - including processing the Invalidate() call.

- Scott

JoeFallon1 replied on Friday, January 25, 2008

Sco,

Welcome!

FYI - The status busy class is not part of CSLA. It is just something Rocky threw together for Project Tracker which is a simple sample app showing off many ways to use CSLA. Do not take things in Project tracker as "gospel". There are many ways to build and use BOs. Feel free to ask and do searches on the forum.

Joe

 

JonM replied on Monday, January 28, 2008

Call the Invalidate.  Then call the Application.DoEvents() method.

ajj3085 replied on Monday, January 28, 2008

Yuck.  DoEvents is evil.  It can cause threading issues in and of itself, because the UI may respond to partially loaded data (if you're adding to a grid, for example).   The Background Worker component is very simple to use, and avoids any issues DoEvents may cause.

OldBob-Sco replied on Monday, January 28, 2008

Thanks for the info guys.

I now know not to treat everything as gospel (damn).  As far as I can see there is no data fetching or any other task in hand that is hogging the thread, and the fact that the Caption bar on the Main Form will change when requested to do so would suggest that it will do things you request. It could be a "stack" thing but I'll try not to lose to much sleep over it at the moment, but it's something that I'll keep coming back to (I'm sad that way).

I'm also not sure about the background worker object. Will this be on another thread, and if so, how is that able to update a form that is currently in the process of working in the original thread (if that makes sense). I'm from a single threaded background, and although multithreaded apps appeal, I think I would tread with trepidation. I'll do some research before stepping down that route.

Thanks again
OldBob

OldBob-Sco replied on Monday, January 28, 2008

and as the title says.. yes it was a dumb question. Now, I'll let you guys argue why I shouldn't do this, but adding a simple MainForm.Instance.Refresh() in the StatusBusy displays the message. (D'oh)

ajj3085 replied on Monday, January 28, 2008

Hmm... ok, that should work, as long as your only calling Refresh from the UI thread. I forgot about that method... it does an immediate Repaint.  I see no potential problems, unless you call this from a non-UI thread, but that doesn't sound like your setup.

OldBob-Sco replied on Friday, February 01, 2008

Thanks for the additional info aj.

Re background worker object. I'll need to take some time out and look at them. I'm sure I'll find a use for them.

Re the Refresh. Nope, there is definitely not any non UI code being kicked off that I'm aware of. I've left it like that just now so I can delve deeper into the framework and start to use it in anger. Still getting my head around defining the business objects and trying not to follow the normalised data path. I may come back to you all with more questions.

In the meantime, thanks for the info so far.
OldBob

ajj3085 replied on Monday, January 28, 2008

OldBob-Sco:
I now know not to treat everything as gospel (damn).  As far as I can see there is no data fetching or any other task in hand that is hogging the thread, and the fact that the Caption bar on the Main Form will change when requested to do so would suggest that it will do things you request. It could be a "stack" thing but I'll try not to lose to much sleep over it at the moment, but it's something that I'll keep coming back to (I'm sad that way).


Well, what exactly is your code doing from the time it creates the statusbusy until the end of the using block?  whatever code is in there is what is "hogging" the UI thread.  But if its not data access, I would think whatever code it is would run pretty quickly.

OldBob-Sco:
I'm also not sure about the background worker object. Will this be on another thread, and if so, how is that able to update a form that is currently in the process of working in the original thread (if that makes sense). I'm from a single threaded background, and although multithreaded apps appeal, I think I would tread with trepidation. I'll do some research before stepping down that route.


The background worker is a component.  You wire two event handlers (three if you want progress reporting).  The DoWork event is the code that will execute on a seperate thread.  The WorkerComplete event (or someting like that) is the event that fires after DoWork has exited.  A typical usage would be to disable your UI controls, then call backgroundWorker.StartAsync, which will handle creating a new thread and running the code (which is in DoWork).  That call returns right away, and normally your event handler is done.  Your UI is disabled, adn eventually WorkerCompleted fires, which you would use to get the business object (or othr data) back, and re-enable your UI controls.

Copyright (c) Marimer LLC