Windows Service Database Update - c#

I have a windows service that polls an Oracle database at a given interval and, based on some criteria, updates several fields. To do this it opens a cursor and iterates through the rows to update.
protected override void OnStart(string[] args)
{
TimerCallback timerDelegate = new TimerCallback(DoStuff);
serviceTimer = new Timer(timerDelegate, null, 0, 20000);
}
private void DoStuff(object state)
{
// Set-up connectionsString and sqlQuery
using (OracleConnection oraConnect = new OracleConnection(connectionString))
{
oraConnect.Open();
using (OracleCommand oraCommand = new OracleCommand(sqlQuery, oraConnect))
using (OracleDataReader oraReader = oraCommand.ExecuteReader())
{
while (oraReader.Read())
{
// Do some processing here – may take some time
// Update database here
}
}
}
My question is, say for example the timer interval is 20 seconds (as above). What happens if the cursor takes 30 seconds to iterate through? I realise that each timer will work in a separate thread, but given that a new database connection is established each time, will the second call see the changes made by the first?

The second process will only see changes committed by the first. If the second process starts before the first commits, then it will not see the changes made by the first.
The assumption made is that one commit is performed in your process. If you are performing a commit after each update, then all bets are off. Your second process will see some of the updates performed by the first, but not all - only those committed when the cursor is opened in the second process.

If you scare that the cursor takes more than 20seconds, you can stop your timer before processes, and then re-start timer after process completed. Is it possible for you to stop timer before process?

Related

c# MySql stored procedure timeout

I have a c# application that calls the same mysql stored procedure multiple times with different parameters. Its called about 250 times and each call takes about 30 seconds to complete.
There are some cases when for some reason a call takes much more time, and it blocks the next ones from running, so I would like to set a timeout for the stored procedures to stop when it takes more than say like 5 minutes. This way the others could still run and only the one that took too much time would be skipped.
I tried to use the command timeout of the mysql connection, but this does not kill the running stored procedure, only throws an exception in code which is not ideail because the next call will start while the previous one is still running.
Is there a way to set a mysql timout for the connection, or just kill a mysql thread/process (the sp) if it takes too much time? Closing the mysql command or connection did not do it, and clearing the connection pool did not help either.
To kill a running stored procedure, use MySqlCommand.Cancel (using the same MySqlCommand object that was used to start that stored procedure). Because MySqlCommand.ExecuteNonQuery (or ExecuteReader, etc.) will block the thread that called it, this will have to be done from another thread. One way to accomplish this would be with CancellationTokenSource, then registering a callback that will cancel the command:
// set up command
using (var command = new MySqlCommand("sproc_name", connection))
{
command.CommandType = CommandType.StoredProcedure;
// register cancellation to occur in five minutes
using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5)))
using (cts.Token.Register(() => command.Cancel())
{
// execute the stored procedure as normal
using (var reader = command.ExecuteReader())
{
// use reader, or just call command.ExecuteNonQuery instead if that's what you need
}
}
}

Keeping console app from closing but still run codes

I have a console app that does not terminate using a code
new System.Threading.AutoResetEvent(false).WaitOne();
What I want to achieve: I would want to run a StopWatch and if it meets a condition it will run certain file manipulating codes. And then finally after the block of code, resets the timer and wait for it to be true again to rerun.
Problem: However, upon debugging I cant get my code to go through my conditions even it has already passed the required condition.
My Code:
static void Main(string[] args)
{
string mutex_id = "41585f436f766572743243494d";
using (System.Threading.Mutex mtx = new System.Threading.Mutex(false, mutex_id))
{
if(!mtx.WaitOne(0,false))
{
return;
}
processTimer = new Stopwatch();
processTimer.Start();
if (processTimer.Elapsed.Seconds > 10)
{
processTimer.Stop();
fileQueue = Directory.GetFiles(ConfigurationManager.AppSettings["WatchPath"], ConfigurationManager.AppSettings["Format"]).ToList();
}
//process the fileQueue
//..
//..
//processTimer.Reset(); -> Reset Timer to wait for another 10 sec and process again
new System.Threading.AutoResetEvent(false).WaitOne();
}
}
I have used a FileSystemWatcher before but I failed to get the process correctly(Like Consecutive/Concurrent file creations and such). Tried Threading and Timers as my question.
Now I'm trying to approach this issue from a new perspective. Hope some can enlighten me with this.
There is no "try again" in your code.
The code you've written does the following:
Create a mutex and lock it
If it already exists, close application
Start a stopwatch
Check if 10 seconds elapsed (which they didn't)
Create a new AutoResetEvent and wait for ever for it
You will need some loop that periodically checks if 10 seconds have passed and otherwise Sleep

WPF DispatcherTimer Memory Issue

Edit: If useful, this project is on GitHub at https://github.com/lostchopstik/BetterBlync
I am building an application for the Blync status light using their provided API. This application polls the Lync/Skype for Biz client and converts the status to the appropriate light color. All aspects thus far work as expected, however when I leave this program running for an extended period of time, the memory usage grows until a System.OutOfMemory exception occurs.
I have narrowed the problem down to the DispatcherTimer holding the timer in memory and preventing it from being GCed. After reading some things online I found you could manually call for garbage collection, but this is bad practice. Regardless, here is what I have in my code right now:
private void initTimer()
{
timer = new DispatcherTimer();
timer.Interval = new TimeSpan( 0, 0, 0, 0, 200 );
timer.Tick += new EventHandler( Timer_Tick );
timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
// Check to see if any new lights are connected
blync.FindBlyncLights();
// Get current status from Lync client
lync.GetStatus();
// Change to new color
setStatusLight();
if ( count++ == 100 )
{
count = 0;
GC.Collect();
}
}
The timer ticks every 200ms. I commented out all methods inside the timer and just let it run empty, and it still burned memory.
I am wondering what the proper way to handle this timer is. I've used the DispatcherTimer in the past and not had this issue.
I would also be open to trying something besides the DispatcherTimer.
If it is also useful, I have been messing with MemProfiler and here as my current graph with manual GC:
http://imgur.com/Iut91mF
It's a little hard to tell without seeing the rest of the code or the class the timer belongs to. I don't see anywhere you call Stop() on the timer. Does it need to be stopped?
You could also keep a local reference to the timer in whatever class you're in and call Start() and Stop() as needed.
If the timer never needs to be stopped and runs indefinitely, I would certainly look at what you're allocating as the timer runs and that's probably where your issue is.

Threading doesn't work correctly

I have an application, which is to repeat the numbers what I hear then record the digits what I read. The numbers are 0,1,2,3,4,5,6,7,8,9. I use a for loop to play these numbers with a text to speech skill, which is from a third party.
For the recording part, I have to put it in a separate thread by the third party requirement. To record the voice, the method is likely:
recordVoiceResource.Record(fileName);
To stop it, use:
recordVoiceResource.Stop();
Now I find sometimes my recording is 0 second, which means the code perhaps doesn't reach Record line. Sometimes it only has 2 seconds. I believe the thread schedule is wrong.
private ManualResetEvent terminate = new ManualResetEvent(false);
PlayTTS("Please repeat the following numbers as you hear them.");
Thread t = new Thread(() => RecordNumbers());
t.Start();
Thread.Sleep(2000);
terminate.Set();
terminate.WaitOne();
PlayNumbers();
recordVoiceResource.Stop();
The thread method is:
private void RecordNumbers()
{
recordVoiceResource = TelephonyServer.GetVoiceResource();
recordVoiceResource.MaximumSilence = 1;
recordVoiceResource.MaximumTime = 30;
// Start recording what I read from I heard
recordVoiceResource.Record(fileName);
}
To playNumbers,
private void PlayNumbers()
{
foreach (var item in numbers)
{
try
{
vr.PlayTTS(item.ToString()); // will be 0,1,2,...9
Thread.Sleep(2000);
}
According to your comment, the property MaximumSilence gets or sets the maximum silence in seconds that will be allowed until termination of the next voice function. You are setting it to one second, starting the recording, and then sleeping for two seconds before beginning playback that prompts the user to say something. Do you see the problem here? Assuming the mic doesn't pick up some unrelated speech during that period, the recording will stop before the playback even begins.
Since there is a 2-second gap between number playback, you probably need to set MaximumSilence to several seconds.
That is, of course, assuming your intention was to capture a single recording of the user speaking all the numbers (which is how your code is written). If you want to capture the spoken numbers individually, then you may need to schedule and synchronize separate recordings as each number is played back. You may want to double-check the API to make sure your solution is what you intended.
It is very likely your problem is causing due to Thread.Sleep(). Use a timer instead:
System.Timers.Timer Record = new System.Timers.Timer();
Record.Interval = 2000;
Record.Elapsed += new System.Timers.ElapsedEventHandler(Record_Elapsed);
void Record_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Record.Enabled=false;
PlayNumbers();
recordVoiceResource.Stop();
}
And set:
Thread t = new Thread(() => RecordNumbers());
t.Start();
Record.Enabled=true;

Performance Counter - System.InvalidOperationException: Category does not exist

I have following class that returns number of current Request per Second of IIS. I call RefreshCounters every minute in order to keep Requests per Second value refreshed (because it is average and if I keep it too long old value will influence result too much)... and when I need to display current RequestsPerSecond I call that property.
public class Counters
{
private static PerformanceCounter pcReqsPerSec;
private const string counterKey = "Requests_Sec";
public static object RequestsPerSecond
{
get
{
lock (counterKey)
{
if (pcReqsPerSec != null)
return pcReqsPerSec.NextValue().ToString("N2"); // EXCEPTION
else
return "0";
}
}
}
internal static string RefreshCounters()
{
lock (counterKey)
{
try
{
if (pcReqsPerSec != null)
{
pcReqsPerSec.Dispose();
pcReqsPerSec = null;
}
pcReqsPerSec = new PerformanceCounter("W3SVC_W3WP", "Requests / Sec", "_Total", true);
pcReqsPerSec.NextValue();
PerformanceCounter.CloseSharedResources();
return null;
}
catch (Exception ex)
{
return ex.ToString();
}
}
}
}
The problem is that following Exception is sometimes thrown:
System.InvalidOperationException: Category does not exist.
at System.Diagnostics.PerformanceCounterLib.GetCategorySample(String machine,\ String category)
at System.Diagnostics.PerformanceCounter.NextSample()
at System.Diagnostics.PerformanceCounter.NextValue()
at BidBop.Admin.PerfCounter.Counters.get_RequestsPerSecond() in [[[pcReqsPerSec.NextValue().ToString("N2");]]]
Am I not closing previous instances of PerformanceCounter properly? What am I doing wrong so that I end up with that exception sometimes?
EDIT:
And just for the record, I am hosting this class in IIS website (that is, of course, hosted in App Pool which has administrative privileges) and invoking methods from ASMX service. Site that uses Counter values (displays them) calls RefreshCounters every 1 minute and RequestsPerSecond every 5 seconds; RequestPerSecond are cached between calls.
I am calling RefreshCounters every 1 minute because values tend to become "stale" - too influenced by older values (that were actual 1 minute ago, for example).
Antenka has led you in a good direction here. You should not be disposing and re-creating the performance counter on every update/request for value. There is a cost for instantiating the performance counters and the first read can be inaccurate as indicated in the quote below. Also your lock() { ... } statements are very broad (they cover a lot of statements) and will be slow. Its better to have your locks as small as possible. I'm giving Antenka a voteup for the quality reference and good advice!
However, I think I can provide a better answer for you. I have a fair bit of experience with monitoring server performance and understand exactly what you need. One problem your code doesn't take into account is that whatever code is displaying your performance counter (.aspx, .asmx, console app, winform app, etc) could be requesting this statistic at any rate; it could be requested once every 10 seconds, maybe 5 times per second, you don't know and shouldn't care. So you need to separate the PerformanceCounter collection code from that does the monitoring from the code that actually reports the current Requests / Second value. And for performance reasons, I'm also going to show you how to setup the performance counter on first request and then keep it going until nobody has made any requests for 5 seconds, then close/dispose the PerformanceCounter properly.
public class RequestsPerSecondCollector
{
#region General Declaration
//Static Stuff for the polling timer
private static System.Threading.Timer pollingTimer;
private static int stateCounter = 0;
private static int lockTimerCounter = 0;
//Instance Stuff for our performance counter
private static System.Diagnostics.PerformanceCounter pcReqsPerSec;
private readonly static object threadLock = new object();
private static decimal CurrentRequestsPerSecondValue;
private static int LastRequestTicks;
#endregion
#region Singleton Implementation
/// <summary>
/// Static members are 'eagerly initialized', that is,
/// immediately when class is loaded for the first time.
/// .NET guarantees thread safety for static initialization.
/// </summary>
private static readonly RequestsPerSecondCollector _instance = new RequestsPerSecondCollector();
#endregion
#region Constructor/Finalizer
/// <summary>
/// Private constructor for static singleton instance construction, you won't be able to instantiate this class outside of itself.
/// </summary>
private RequestsPerSecondCollector()
{
LastRequestTicks = System.Environment.TickCount;
// Start things up by making the first request.
GetRequestsPerSecond();
}
#endregion
#region Getter for current requests per second measure
public static decimal GetRequestsPerSecond()
{
if (pollingTimer == null)
{
Console.WriteLine("Starting Poll Timer");
// Let's check the performance counter every 1 second, and don't do the first time until after 1 second.
pollingTimer = new System.Threading.Timer(OnTimerCallback, null, 1000, 1000);
// The first read from a performance counter is notoriously inaccurate, so
OnTimerCallback(null);
}
LastRequestTicks = System.Environment.TickCount;
lock (threadLock)
{
return CurrentRequestsPerSecondValue;
}
}
#endregion
#region Polling Timer
static void OnTimerCallback(object state)
{
if (System.Threading.Interlocked.CompareExchange(ref lockTimerCounter, 1, 0) == 0)
{
if (pcReqsPerSec == null)
pcReqsPerSec = new System.Diagnostics.PerformanceCounter("W3SVC_W3WP", "Requests / Sec", "_Total", true);
if (pcReqsPerSec != null)
{
try
{
lock (threadLock)
{
CurrentRequestsPerSecondValue = Convert.ToDecimal(pcReqsPerSec.NextValue().ToString("N2"));
}
}
catch (Exception) {
// We had problem, just get rid of the performance counter and we'll rebuild it next revision
if (pcReqsPerSec != null)
{
pcReqsPerSec.Close();
pcReqsPerSec.Dispose();
pcReqsPerSec = null;
}
}
}
stateCounter++;
//Check every 5 seconds or so if anybody is still monitoring the server PerformanceCounter, if not shut down our PerformanceCounter
if (stateCounter % 5 == 0)
{
if (System.Environment.TickCount - LastRequestTicks > 5000)
{
Console.WriteLine("Stopping Poll Timer");
pollingTimer.Dispose();
pollingTimer = null;
if (pcReqsPerSec != null)
{
pcReqsPerSec.Close();
pcReqsPerSec.Dispose();
pcReqsPerSec = null;
}
}
}
System.Threading.Interlocked.Add(ref lockTimerCounter, -1);
}
}
#endregion
}
Ok now for some explanation.
First you'll notice this class is designed to be a static singleton.
You can't load multiple copies of it, it has a private constructor
and and eagerly initialized internal instance of itself. This makes
sure you don't accidentally create multiple copies of the same
PerformanceCounter.
Next you'll notice in the private constructor (this will only run
once when the class is first accessed) we create both the
PerformanceCounter and a timer which will be used to poll the
PerformanceCounter.
The Timer's callback method will create the PerformanceCounter if
needed and get its next value is available. Also every 5 iterations
we're going to see how long its been since your last request for the
PerformanceCounter's value. If it's been more than 5 seconds, we'll
shutdown the polling timer as its unneeded at the moment. We can
always start it up again later if we need it again.
Now we have a static method called GetRequestsPerSecond() for you to
call which will return the current value of the RequestsPerSecond
PerformanceCounter.
The benefits of this implementation are that you only create the performance counter once and then keep using until you are finished with it. Its easy to use because you simple call RequestsPerSecondCollector.GetRequestsPerSecond() from wherever you need it (.aspx, .asmx, console app, winforms app, etc). There will always be only one PerformanceCounter and it will always be polled at exactly 1 times per second regardless of how quickly you call RequestsPerSecondCollector.GetRequestsPerSecond(). It will also automatically close and dispose of the PerformanceCounter if you haven't requested its value in more than 5 seconds. Of course you can adjust both the timer interval and the timeout milliseconds to suit your needs. You could poll faster and timeout in say 60 seconds instead of 5. I chose 5 seconds as it proves that it works very quickly while debugging in visual studio. Once you test it and know it works, you might want a longer timeout.
Hopefully this helps you not only better use PerformanceCounters, but also feel safe to reuse this class which is separate from whatever you want to display the statistics in. Reusable code is always a plus!
EDIT: As a follow up question, what if you want to performance some cleanup or babysitting task every 60 seconds while this performance counter is running? Well we already have the timer running every 1 second and a variable tracking our loop iterations called stateCounter which is incremented on each timer callback. So you could add in some code like this:
// Every 60 seconds I want to close/dispose my PerformanceCounter
if (stateCounter % 60 == 0)
{
if (pcReqsPerSec != null)
{
pcReqsPerSec.Close();
pcReqsPerSec.Dispose();
pcReqsPerSec = null;
}
}
I should point out that this performance counter in the example should not "go stale". I believe 'Request / Sec" should be an average and not a moving average statistic. But this sample just illustrates a way you could do any type of cleanup or "babysitting" of your PerformanceCounter on a regular time interval. In this case we are closing and disposing the performance counter which will cause it to be recreated on next timer callback. You could modify this for your use case and according the specific PerformanceCounter you are using. Most people reading this question/answer should not need to do this. Check the documentation for your desired PerformanceCounter to see if it is a continuous count, an average, a moving average, etc... and adjust your implementation appropriately.
I don't know, if this passes you .. I've read article PerformanceCounter.NextValue Method
And there was a comment:
// If the category does not exist, create the category and exit.
// Performance counters should not be created and immediately used.
// There is a latency time to enable the counters, they should be created
// prior to executing the application that uses the counters.
// Execute this sample a second time to use the category.
So, I have a question, which can lead to answer: isn't call to a RequestsPerSecond method happends too early?
Also, I would suggest you to to try check if the Category doesn't exists and log the info somewhere, so we can analyze it and determine which conditions we have and how often that happends.
I just solved this type of error or exception with:
Using,
new PerformanceCounter("Processor Information", "% Processor Time", "_Total");
Instead of,
new PerformanceCounter("Processor", "% Processor Time", "_Total");
I had an issue retrieving requests per second on IIS using code similar to the following
var pc = new PerformanceCounter();
pc.CategoryName = #"W3SVC_W3WP";
pc.InstanceName = #"_Total";
pc.CounterName = #"Requests / Sec";
Console.WriteLine(pc.NextValue());
This would sometimes throw InvalidOperationException and I was able to reproduce the exception by restarting IIS. If I run with a non warmed up IIS, e.g. after a laptop reboot or IIS restart, then I get this exception. Hit the website first, make any http request beforehand, and wait a second or two and I don't get the exception. This smells like the performance counters are cached,and when Idle they get dumped, and take a while to re-cache? (or similar).
Update1: Initially when I manually browse to the website and warm it up, it solves the problem. I've tried programmatically warming up the server with new WebClient().DownloadString(); Thread.Sleep() up to 3000ms and this has not worked? So my results of manually warming up server, might somehow be a false positive. I'm leaving my answer here, because it might be the cause, (i.e. manual warming up), and maybe someone else can elaborate further?
Update2: Ah, ok, here are some unit tests that summarises some learning from further experimenting I did yesterday. (There's not a lot on google on this subject btw.)
As far as I can reason, the following statements might be true; (and I submit the unit tests underneath as evidence.) I may have misinterpreted the results, so please double check ;-D
Create a performance counter and calling getValue before the category exists, e.g. querying an IIS counter, while IIS is cold and no process running, will throw InvalidOperation exception "category does not exist". (I assume this is true for all counters, and not just IIS.)
From within a Visual Studio unit test, once your counter throws an exception, if you subsequently warm up the server after the first exception, and create a new PerformanceCounter and query again, it will still throw an exception! (this one was a surprise, I assume this is because of some singleton action. My apologies I have not had enough time to decompile the sources to investigate further before posting this reply.)
In 2 above, if you mark the unit test with [STAThread] then I was able to create a new PerformanceCounter after one has failed. (This might have something to do with Performance counter possibly being singletons? Needs further testing.)
No pause was required for me before creating counter and using it, despite some warnings in MSDN same code documentation, other than the time it takes to create a performance counter itself before calling NextValue().In my case, to warm up the counter and bring the "category" into existance, was for me to fire one shot across the bow of IIS, i.e. make a single GET request, and viola, no longer get "InvalidOperationException", and this seems to be a reliable fix for me, for now. At least when querying IIS performance counters.
CreatingPerformanceCounterBeforeWarmingUpServerThrowsException
[Test, Ignore("Run manually AFTER restarting IIS with 'iisreset' at cmd prompt.")]
public void CreatingPerformanceCounterBeforeWarmingUpServerThrowsException()
{
Console.WriteLine("Given a webserver that is cold");
Console.WriteLine("When I create a performance counter and read next value");
using (var pc1 = new PerformanceCounter())
{
pc1.CategoryName = #"W3SVC_W3WP";
pc1.InstanceName = #"_Total";
pc1.CounterName = #"Requests / Sec";
Action action1 = () => pc1.NextValue();
Console.WriteLine("Then InvalidOperationException will be thrown");
action1.ShouldThrow<InvalidOperationException>();
}
}
[Test, Ignore("Run manually AFTER restarting IIS with 'iisreset' at cmd prompt.")]
public void CreatingPerformanceCounterAfterWarmingUpServerDoesNotThrowException()
{
Console.WriteLine("Given a webserver that has been Warmed up");
using (var client = new WebClient())
{
client.DownloadString("http://localhost:8082/small1.json");
}
Console.WriteLine("When I create a performance counter and read next value");
using (var pc2 = new PerformanceCounter())
{
pc2.CategoryName = #"W3SVC_W3WP";
pc2.InstanceName = #"_Total";
pc2.CounterName = #"Requests / Sec";
float? result = null;
Action action2 = () => result = pc2.NextValue();
Console.WriteLine("Then InvalidOperationException will not be thrown");
action2.ShouldNotThrow();
Console.WriteLine("And the counter value will be returned");
result.HasValue.Should().BeTrue();
}
}
Just out of curiousity, what do you have set for properties in Visual Studio? In VS go to Project Properties, Build, Platform target and change it to AnyCPU. I have seen it before where Performance Counters aren't always retrieved when it is set to x86, and changing it to AnyCPU could fix it.

Categories