NozFx

Hi all,

I need to spawn my own thread outside of the CLR's threadpool that waits for a notification within a time-out that is not going to hog the processor. Phew, what a mouthful.

Ok let me expand on that a little. Basically I have an ASP.NET application with an Asynchronous HTTP Handler that passes a device ID to my new seperate thread. (Ok the fact I'm using ASP.NET should not be a factor here). This thread needs to use this DeviceID to check for any updates that are held in a queue. This queue will reside in a SQL server 2005 DB. This does not have to be the case though.

Basically I need a processor efficiant way of waiting for a job to appear in the queue for the device ID in question. It is very important that while this thread is waiting that it does not hog the CPU. Can anyone offer any advice on the best way to go about this My first thought was to use file notification, but on second thoughts disk IO is expensive. Can anyone point me to an example that could help me with this one

TIA

Richard



Re: Visual C# General Processor efficient loops (notifications).

Matthew Watson

What is the timeframe within which your thread must respond to the item appearing in the queue

If within a second or so will do, you can just write a polling loops that calls something like Thread.Sleep(1000) every iteration.

(You'll need to check two conditions for each iteration, of course: (i) is there anything in the queue and (ii) should the poll loop terminate for some other reason.)




Re: Visual C# General Processor efficient loops (notifications).

NozFx

Hi Matthew,

Thanks for your reply, much appreciated.

I haven't actually defined this time-frame yet. I think I would start with something like 1 second and see how that performed.

Yes I would need to check to see if the poll should time-out. I actually want the server to respond before the client request times-out so that the client cleanly knows the server is operating correctly.

I'm happy with sleeping the thread in this manner but it all depends on how quickly and efficiantly I can check the queue. I'm not sure of the perf hit on the CPU when querying a SQL DB using the .NET framework. I know this will depend on the method used to connect to the DB and the method used the return the data. I do not know the most CPU performant way to query a DB using the framework. I also don't know if querying the DB is really as performant as I will need to be for this application. If not, I will have to get the SQL server to output these notifications in a different way in order for the app to poll for the notification.

Any suggestions

Thanks

NozFx





Re: Visual C# General Processor efficient loops (notifications).

Chuck the Code Monkey

Polling should not be necessary. Using reset events, you can wait for an event to be triggered and you will be waiting in a sleep state not consuming any CPU. When ever your data is ready, then the event can be triggered signaling the worker thread to process it's data.

private AutoResetEvent trigger = new AutoResetEvent(false);

private void DoStuff(int msToWait)
{
if (trigger.WaitOne(msToWait, false))
{
//Perform the desired work
}
else
{
//Deal with a timeout
}
}

Whenever your data is ready, then trigger.Set() can be called signaling DoStuff that it's data is ready.







Re: Visual C# General Processor efficient loops (notifications).

NozFx

Hi Chuck,

Thank you for your reply.

This sounds like the solution I need. I've not done this before, could you explain how I would use the trigger.Set(). Is this a seperate process or thread that continually looks for updates How would I go about implementing this with data on a SQL server

Sorry if this is application specific. If you could provide any more details or point me to some resources I would greatly appreciate it.

Thanks

NozFx





Re: Visual C# General Processor efficient loops (notifications).

IsshouFuuraibou

Basically the trigger would be set when you receive messages from the queue. You may need to work out your own event/callback system for managing new arrivals to the queue.

Ideally your method for adding a job to the queue is what calls trigger.Set() to indicate that you have a job in the queue. However, it is not clear enough from your description how you are making and adding jobs to your queue. In some cases this may not be possible if you don't have enough control over adding to the queue.





Re: Visual C# General Processor efficient loops (notifications).

Chuck the Code Monkey

Trigger may have been a confusing term for me to name the variable as triggers are a database term as well, I apologize. This would be all on the C# side. Essentially you have 1 thread that produces data while another thread consumes that data, both running at the same time. The AutoResetEvent is the synchronization object between the two threads. In pseudo code, the operation would work as follows:

AutoResetEvent sync = new AutoResetEvent(false)

ProducerThread
{
Do some stuff that creates data to be processed
(In your case, it may be retrieve a data set from a SQL server)

Once the data is ready, then:
sync.Set(); //This statement lets the consumer thread know that it's data is ready
}

ConsumerThread
{
if(sync.WaitOne(1000, false))
{
The event has been triggered so the data is ready to process
}
else
{
The event was not triggered in time
}
}

"Threading in C#" is a great e-book that can be found at:
http://www.albahari.com/threading/threading.pdf
Although many of the topics may be a bit overkill for your situation. The MSDN documentation for the AutoResetEvent and the examples it provides are quite helpful.





Re: Visual C# General Processor efficient loops (notifications).

NozFx

Hi Chuck,

Oh its ok, I understand what the trigger was for. Its just my problem is that I have no thread checking the data, I didn't think in terms of having one thread for this job. If I have 20 threads checking a DB things are going to get hairy so this does offer a solution. I suppose with this solution I can have one thread polling the data and then signalling these events as and when necessary. Trouble is this starts to get very complicated, and that is a big no no <bg>. I like to keep things simple ;)

I'm not sure if I could use this in this example as I'm using ASP.NET here. I would have to hook into the start of my application pool in order to create this single worker thread to poll the database for data. I then have to find some way of registering these AutoResetEvents with this thread as and when the requests come in. Now this solution does seem neat but again it doesn't answer how CPU hungry the DB checking is going to be.

I've got choices now haven't I. Looping around and checking the db is going to be less efficiant than sitting in a wait state. Saying that I need some thread to signal the wait in order to free the thread. Do you think polling in this manner is too much overhead If so am I going to have to delve deeper and look to see what SQL notification services can do to help I suppose this one is for the SQL guys <g>

Thanks for the advice and thanks for the references; I will check out these as well.

NozFx





Re: Visual C# General Processor efficient loops (notifications).

Chuck the Code Monkey

The e-book I referenced you to has a decent section on the Producer/Consumer problem describing several scenarios with many Consumer or Worker threads. Hopefully you can find some good info in there.





Re: Visual C# General Processor efficient loops (notifications).

NozFx

Hi Chuck,

Sorry I didn't see your first post, sorry. I didn't want to go into too much detail about the application to avoid being app specific but I suppose it needs to be explained. Its just this application is an ASP.NET app and this may not be the place to ask. Heres the background to why I posted this thread:

Basically the jobs get added through a completely seperate web application framework. Its actually a web framework for VFP with its own ISAPI bridge application. The problem is I cannot achieve what I'm after with the application for one specific task. This task is AUTD (Always-Up-To-Date). The web server will be servicing Windows Mobile applications working over the highly disconnected GPRS network. I want to provide a simulated PUSH network interface similar to Exchange 2003 SP2 Push email system. They have achived this with extended HTTP/HTTPS requests in which the server holds the request a long time until it finds some data or times-out. The problem is the VFP framework just will not handle the load this will cause. Its just too high level. ASP.NET offers more flexibility and even a way to achieve this but if I go about it using the page framework or standard handlers in .NET, I would use up the application thread-pool and even global threadpool very fast when more than 20 devices are connecting. Now I can get round this using Asynchronous HTTP Handlers in which I can spawn my own worker threads (great). Trouble is these threads must not be CPU intensive in order to make the application scaleable. So if these threads are polling a SQL DB I probably have broken this rule already. I cannot have the CPU hogged with these async requests!

I hope this explained where I'm comming from a little. Maybe I'm worrying too much here, but I just wondered, if I do not have any in-process code adding to the job queue in this ASP.NET app then what would be the best way to get these data updates to signal these worker threads efficiantly I suppose I may not able to and will just have to live with a polling solution.

Thanks Again

NozFx





Re: Visual C# General Processor efficient loops (notifications).

Matthew Watson

At the end of the day, either the database engine must alert your thread (which means that you need a trigger/stored procedure), or some thread somewhere will have to poll it.

If you want to avoid polling the database, a trigger/stored procedure is the only solution (as far as I know).





Re: Visual C# General Processor efficient loops (notifications).

NozFx

Hi Matthew,

Thanks for your reply. Ah, so I could fire a trigger that calls the ASP.NET application and then notify the other threads. I'll get to work on this I think.

Many Thanks

NozFx