Presentation Layer vs. Business Logic Layer

  • Thread starter Michael Rodriguez
  • Start date
M

Michael Rodriguez

I have a windows form that makes a call to my BLL to get some data. The
windows form has a progress bar component that I would like updated as the
data retrieval takes place. However, strictly speaking, the BLL is not
supposed to know anything about the presentation layer. Also, since the
presentation layer has a reference to the BLL, it won't let me add a
reference to the presentation layer from the BLL, it complains about a
"circular dependency".

What's the best way for my BLL to inform my winforms layer about it's
progress and update such in a progress bar?

TIA,

Mike Rodriguez
 
J

James

What you could do is create an Event in your BLL that your GUI Layer can
subscribe to to get notification that rows are being read/written in your
BLL layer. Now the BLL layer fires this event but does not have to know
anything about what the receiver of this event is doing with it. This
provides separation between layers. Or you could simply do a timer in the
GUI and start it before the call to the BLL and stop it after the call
returns, and update your progress bar from the timer event.

JIM
 
B

Bruce Wood

There are several ways you could do this.

First, have your business logic layer publish an event that it fires
while it's processing the request. The event could contain information
about what the BLL is doing (processing Customer 104423), or how far
along it is in the task it's been given, as a percentage or a count and
a total (100 of 1204), or both a message and a count and total.

Your presentation layer could then create a progress bar and subscribe
to the appropriate event. Every time the BLL fires the event, the
presentation layer updates the progress bar.

A second option is that the BLL publishes a delegate that it promises
to call at intervals during its task. You either pass a delegate method
on the call to the BLL, or you pass null. If you pass a delegate, the
BLL calls it at intervals during its task, passing the same information
as it would have included on the event.

I prefer the second option, personally, as you have to pass the
delegate on the call to the BLL and so the connection between the
delegate method and the task is clearer in your presentation layer.
However, it does lead to messier code in the BLL, which has to pass the
delegate around to where it's needed.

Also note that in both of these cases if you're not using a background
thread for the BLL task then you have to call Application.DoEvents() in
your delegate method in order to redraw the progress bar.

Both of these methods assume that the BLL can indicate meaningful
progress. That is, that most of its time isn't taken up doing one, big
query from a database or something, during which it doesn't have
control of the thread and so cannot call the delegate, then you have to
have a stand-alone progress bar that runs on the UI thread, and run the
BLL in the background thread, with no communication between the two. I
once found an article about how to build a smart progress bar that
"remembers" how long each operation took "last time" and uses that as
an estimate for how fast to progress "this time." Unfortunately, I've
lost it, but I'm sure that Google can dig something like that up fairly
quickly.
 
W

Wayne

You sure DoEvents or a thread is required? I did the following in a button
click on a form, and the progress bar updated just as it should. Seems like
the Value property set must be calling it's paint method when the value
changes.


for (int i = 0; i <= 50000; i++)

{

progressBar1.Value = i;

}


--
Thanks
Wayne Sepega
Jacksonville, Fl


"When a man sits with a pretty girl for an hour, it seems like a minute. But
let him sit on a hot stove for a minute and it's longer than any hour.
That's relativity." - Albert Einstein
 
B

Bruce Wood

Perhaps the ProgressBar class calls DoEvents internally. That would
make sense, considering its purpose.

I was speaking more along the lines of if the OP were to construct his
own progress bar class. I forgot that the framework already supplies
one. :)
 
S

Samuel R. Neff

The ProgressBar internally sends a PBM_SETPOS message which
immediately updated the progress bar but it does not process any other
pending windows messages. The result is that the ProgressBar itself
will be responsive but the app as a whole will appear locked up (it
won't react to moving the main form and all other controls will be
non-reactive).

While calling DoEvents will make the app responsive and is better than
nothing, it involves overhead of it's own in identifying and
processing the message loop synchronously. As such, long running
operations such as this are better off moved to a separate thread
where events can be used to update the UI of progress.

Best regards,

Sam


Perhaps the ProgressBar class calls DoEvents internally. That would
make sense, considering its purpose.

I was speaking more along the lines of if the OP were to construct his
own progress bar class. I forgot that the framework already supplies
one. :)

B-Line is now hiring one Washington D.C. area VB.NET
developer for WinForms + WebServices position.
Seaking mid to senior level developer. For
information or to apply e-mail resume to
sam_blinex_com.
 
W

Wayne

I seriously doubt that it would call doevents, doing so would cause issues
for the programmer if not taken into account. For example, if you do some
processing under a button click, doevents would allow the user to click the
button while the processing is going on, and this could cause it to reenter
the processing method.

And besides, only the progress bar paints and not the rest of the form.

--
Thanks
Wayne Sepega
Jacksonville, Fl


"When a man sits with a pretty girl for an hour, it seems like a minute. But
let him sit on a hot stove for a minute and it's longer than any hour.
That's relativity." - Albert Einstein
 
R

RCS

But if the background logic was threaded, there would be no need for
DoEvents, because the UI thread would only have an occasional task to do,
that is - update the progress bar.
 
B

Bruce Wood

Absolutely: putting long-running tasks in the background is the best
solution. Unfortunately, multi-threading comes with its own set of
problems. I usually prefer to get the app working first before I start
messing around with threads. Then again, maybe I'm just a scaredy-cat.
:)
 
J

Jon Skeet [C# MVP]

Bruce Wood said:
Absolutely: putting long-running tasks in the background is the best
solution. Unfortunately, multi-threading comes with its own set of
problems. I usually prefer to get the app working first before I start
messing around with threads. Then again, maybe I'm just a scaredy-cat.
:)

I think it's best to design threading in from the start. It's *much*
harder to retro-fit it onto existing code than to work out from the
start what you want the threads to be, where the points of data-sharing
are, etc.
 
M

Michael Rodriguez

Bruce,

I hadn't thought about the delegate idea. I think I'll try both and see
which one feels better.

Thanks!

Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top