473,383 Members | 1,952 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,383 software developers and data experts.

Philosophical/design question...thoughts solicited

Greetings, all. I have a philosophical/design question for you.

Consider a fairly typical scenario involving a producer/consumer pattern. Now, consider two possible ways of implementing such a pattern in a C-Sharp/.NET Windows Forms application. Presume, for the sake of the discussion framework, the GUI spins up a producer on one thread, and the consumer on the other. As a final constraint on the concept, presume that the Consumer will update the GUI with information from the Producer items. Let's assume further, for the sake of discussion, that proper accomodations will be made in the Consumer-GUI interaction to ensure context switches to the GUI thread when such updates take place.

Now, with that laid out, here are two possible design options regarding the production and consumption of items:

1. The producer could notify the creation of its items of interest via explicitly raised events (exposing appropriate EventHandler delegates), with the consumer subscribing to the events via an appropriate event handler.

2. The producer could, alternatively, add its items to a Queue object. The Queue would be shared between the producer and consumer, with the consumer polling on the queue until items are present to be consumed. Presume all checking on the queue would be wrapped by appropriate lock blocks for thread safety.

I consider pros and cons for each model. My instinct suggests that while the event-based model is probably "purer" from an OO perspective (primarily because there's absolutely no coupling to its caller), my trick knee tells me that the complexity of this solution will start to creep up, particularly if/when the need to implement event asynchronous event handlers arises. I also suspect that the complexity could creep up if it becomes necessary to raise discrete events for each type of item produced. Those combine to suggest to me that there's a risk of the consumer falling behind if the work of consumption starts to take more than a trivial amount of time.

Conversely, we have the "shared queue" model. Clearly, it has stronger coupling through the shared queue. But it does provide for what at least seems to me to be an opportunity for a fairly lightweight polling model - locking the shared queue only when checking for the presence of items, or to enqueue/dequeue items. This model also eliminates what I described earlier as possible "complexity creep" in the event-based model, because the need to raise explicit events as items are produced in this model is eliminated - the producer items are queued, and the consumer consumes them. The producer is also freed to continue producing nearly as rapidly or frequently as it may need, not being burdened with invoking event handlers and thus necessarily relieved of the issue of whether such handlers need to be asychronous. One could call this a "fire and forget" implementation.

With that baseline, what are some other opinions/thoughts on these two possible implementations that I'm possibly overlooking? Is there a clear reason why either should be avoided or preferred?

I realize some of the conclusions would depend upon implementation details I've not provided, hence the warning that the discussion is more philosophical or conceptual than literal at this point.

Thanks in advance.
SoonerDave
Aug 24 '10 #1
3 1310
Aimee Bailey
197 Expert 100+
I know this is a very short reply, and I apologies giving that you have described your query in such a descriptive manner, but I thought id throw my proverbial foot into the mix first.

I've seen this question debated about through many forums over the past couple of years, and one thing that has always stood out, has been the emphasis on choosing a model that tries to make best use of the technology made available, rather than re-inventing the wheel so to speak by developing a locking system. Even though the latter choice offers a direct method of tuning performance, I believe that it inevitably creates overhead.

If I can muster up anything else to add, I'll surely let you know :) though this is quite an interesting one, so i hope other people add their opinion into the mix.

Aimee.
Aug 24 '10 #2
Christian Binder
218 Expert 100+
Standard Windows applications are event-driven and are using the Windows Message Queue.
If I had to create such a producer-consumer-program, I'd prefer using an event-based queue, so if something is enqueued, the consumer is notified and it can request the enqueued item. So you don't have the necessity to poll the queue, what in general isn't the best way (polling).

But it's also depending on how many subscribers there are, so it could be bad, if the first enqueues an item and the second one is missing it out, otherwise if no one removes items from the queue it will overflow.

For your purpose (having one consumer, one producer, program is running as a single process, producer and consumer are just different threads), I'd use a synchronized queue, which sends events if a new item is enqueued. Further, the queue's events should be asyncronous, so that the producer isn't blocked by consumer-sided long-running operations.
Aug 25 '10 #3
balabaster
797 Expert 512MB
I'd combine the two approaches. In C# there's a ManualResetEvent, have your consumer WaitAny. When the producer adds items to the queue, have your consumer loop through the queue until there's no more items left in the queue. When it's finished processing the queue, have it reset the ManualResetEvent. When the producer adds the next item(s), it trips the ManualResetEvent, telling the producer there's items in the queue to process.

This way, your consumer avoids polling, it just sits and waits for the reset event to be tripped allowing it to continue processing, but it still processes everything available without having to wait for the reset event to be tripped per item.

The reset event only really has any effect when the consumer is waiting to process items in the queue.

Let's say the producer is capable of adding items to the queue faster than the consumer is capable of processing them - the consumer only ever sits and waits when there's no items left in the queue to process.

The only lock on the queue you need is right at the end of processing wrapping to check if there's any items left and setting the wait flag, thus reducing the lock to the bare minimum time. The lock needs to be here because if the consumer notes that there's nothing left in the queue and then the producer adds an item and trips the event before the consumer can reset the event, then you get into a position where the consumer is going to sit idle until the producer adds another item while there was already an item in the queue to be processed.

Consumer: Wait for manual reset event; Dequeue Item, Process Item; Lock queue; Check if there's any items remaining in the queue; If there are no items reset event; Unlock queue. Loop around to start...

Producer: Lock queue (waiting for queue to become unlocked if necessary); Add an item to the queue; Trip reset event; Unlock queue.

If the producer doesn't lock the queue ahead of adding the item, the consumer could finish processing the newly added item and reset the event before the producer has a chance to set the event, thus when the producer does set the event, it would trigger the consumer to attempt to process an empty queue.

You can handle this in two ways - either have your consumer account for the possibility of being told to process a queue with zero items in it, or have your producer never tell your consumer to process an empty queue - or both. As a defensive coder, you never know when someone's going to come along and say "Oh, I know what would be a good idea, let's trip that ManualResetEvent from a different process", which causes your consumer to attempt to process a queue which is in an unknown state. So it's probably wise to assume that there will come a time when someone is going to tell your consumer to attempt to process an empty queue. If someone does that, then your consumer should gracefully handle that.

When you're coding in multiple threads you have to consider that something else (including a whole other process) may occur on another thread between *every* line of code. That always needs to be your first and last thought on every call. If you stick to that, you'll be alright.
Aug 30 '10 #4

Sign in to post your reply or Sign up for a free account.

Similar topics

3
by: andy2O | last post by:
Hello comp.lang.py, Can you help me with ideas for the following (somewhat newbie) OO design question in Python? Note, I'm using psuedo-code, not actual Python for the examples! Background:...
0
by: James Walters | last post by:
Hello, DB novice checking in here with a basic design question. I have a table called 'nms_apps' which stores information about all of our applications which we have developed/maintained for...
0
by: Krist | last post by:
Hi All, I have a database design question, pls give me some help.. I want to define tables for salesman's sales target commission . The commission could be given per EITHER sales amount of :...
1
by: Krist | last post by:
Hi All, There is some additional info I forget on this same topic I just posted. I have a database design question, pls give me some help.. I want to define tables for salesman's sales target...
1
by: dixp | last post by:
I'm new to writing multithreaded apps and I have a design question. I have a winforms app and a class which has a method that does processing which is time intensive. I want the user to be able...
3
by: reageer | last post by:
Hi all, I have a design question: I have a bunch of users (name, address, zip, etc.). They are assigned a card with a specific id. The only thing unique is this card id, or probably the...
7
by: Steve Long | last post by:
Hello, I have a design question that I'm hoping someone can chime in on. (I still using VS 2003 .NET 1.1 as our company has not upgraded XP to sp2 yet. duh I know, I know) I have a class I wrote...
29
by: Brad Pears | last post by:
Here is a simple OO design question... I have a Contract class. The user can either save an existing contract or they start off fresh with a blank contract, fill in the data and then save a...
9
by: fjm | last post by:
Hey everyone, I lost my internet connection for about 5 months and finally got it back. This is one of the first places I came back to. I have to say that I had a heck of a time finding it...
2
by: RoaringChicken | last post by:
Hi. Vista Ultimate Access 2007 I'm developing an inventory database and have question on design. The database stores collection details. One item in the collection, one record. The design...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.