I want to create a class that reads SMS messages from a GSM device.
I created a timer(system.threading) that reads for incoming message every second.
public void ReadMessage(){
//read sms messages
//and store it into the database
}
Sometimes ReadMessage() takes more than a second. How can I prevent the timer
from calling this procedure when the previous one is not yet finished?
1. Are AutoResetEvent and WaitOne good for this?
2. Is Threading.Timer a good choice? or should I do it on a single thread?
You should use a System.Timers.Timer, which is easier to work with.
(It's a friendlier wrapper around Threading.Timer)
Set AutoReset to false, then Start() the timer again at the end of the handler.
Don't use a dedicated thread; there's no point in keeping a thread around doing nothing so that you can wake it up every second.
Although this question is quite old, you can inspire by this code. It doesn't use any additional thread and it doesn't count time during execution of your code.
/// <summary>
/// Single thread timer class.
/// </summary>
public class SingleThreadTimer: IDisposable
{
private readonly Timer timer;
private readonly Action timerAction;
/// <summary>
/// Initializes a new instance of the <see cref="SingleThreadTimer"/> class.
/// </summary>
/// <param name="interval">The interval time.</param>
/// <param name="timerAction">The timer action to execute.</param>
/// <exception cref="System.ArgumentNullException">timerAction</exception>
/// <exception cref="System.ArgumentException">interval</exception>
public SingleThreadTimer(double interval, Action timerAction)
{
if (timerAction == null)
throw new ArgumentNullException("timerAction");
if (interval <= 0)
throw new ArgumentException(string.Format("Invalid value '{0}' for parameter 'interval'.", interval), "interval");
this.timerAction = timerAction;
this.timer = new Timer(interval)
{
AutoReset = false
};
timer.Elapsed += timer_Elapsed;
timer.Start();
}
public void Dispose()
{
if (timer != null)
timer.Dispose();
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
timerAction();
}
finally
{
// Enable timer again to continue elapsing event.
timer.Enabled = true;
}
}
}
I cannot see any need for an explicit timer trigger at all. If you thread this off:
while(true){
ReadMessage();
Thread.Sleep(1000);
};
..does this not do exactly what you want, all nicely encapsulated in one thread?
Rgds,
Martin
Related
I have a Winforms application where I am trying to print a pdf document which has multiple layers on it.
But the problem is, This all operation are running on UI thread and it is hanging the UI(not responding) for long time.
I know, this is happening because of UI thread is blocked so, I have tried to make this operation asynchronous by the help of powerful async/await keyword but still my long running method is not being asynchronous. It is not coming forward from the await tasks and still opearation is taking the same time as like synchronous operation.
What I tried:
Please see below:
/// <summary>
/// Show Print Dialog
/// </summary>
private void ShowPrintDialog()
{
// Initialize print dialog
System.Windows.Controls.PrintDialog prtDialog = new System.Windows.Controls.PrintDialog();
prtDialog.PageRangeSelection = PageRangeSelection.AllPages;
prtDialog.UserPageRangeEnabled = false;
_printOptions.PrintQueue = null;
_printOptions.PrintTicket = null;
Enabled = false;
// if there is a default printer then set it
string defaulPrinter = prtDialog.PrintQueue == null ? string.Empty : prtDialog.PrintQueue.FullName;
// Display the dialog. This returns true if the user selects the Print button.
if (prtDialog.ShowDialog() == true)
{
_printOptions.PrintQueue = prtDialog.PrintQueue;
_printOptions.PrintTicket = prtDialog.PrintTicket;
_printOptions.UseDefaultPrinter = (defaulPrinter == prtDialog.PrintQueue.FullName);
}
// Re-enable the form
Enabled = true;
}
/// <summary>
/// Event raised when user clicks Print
/// </summary>
/// <param name="sender">Source of the event</param>
/// <param name="e">Event specific arguments</param>
private void cmdOk_Click(object sender, EventArgs e)
{
ShowPrintDialog();
if (_printOptions.PrintTicket != null)
{
//Set search Options
_print.ExportDataItem = true;
_print.FileName = SearchTemplateName;
//shows progress bar form.
using (frmPrintSearchResultsProgress frmProgress =
new frmPrintSearchResultsProgress(_print, this, _printOptions))
{
frmProgress.ShowDialog(this);
}
if (_print.ExportDataItem && !_print.DataItemExported && !_print.CancelExport)
{
MessageBox.Show("No Document printed.");
}
}
//Store selected options for current user
SaveOptions();
if (!SkipExport)
Close();
}
/// <summary>
/// Event raised when progress form is shown.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void frmExportSearchResultsProgress_Shown(object sender, EventArgs e)
{
try
{
Application.DoEvents();
dispatcher = Dispatcher.CurrentDispatcher;
// record export/print job start time
_startedUtc = DateTime.UtcNow;
_print.WritingToPdfIndicator = lblWritingPdfFile;
lblProgress.Text = Properties.Resources.PrintSearchResults;
await dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(DoDataItemPrint));
}
}
/// <summary>
/// Prints the selected data items.
/// </summary>
private void DoDataItemPrint()
{
// LONG RUNNING OPERATIONS..
// THIS OPERATION IS BLOCKING THE UI.
}
So, as per mentioned in above code when I opened the PringDialogForm then it is opening a Progress Bar form to see the progress of printing the document and from here frmExportSearchResultsProgress_Shown() event is fired and inside it, I am calling the DoDataItemPrint() method which is time consuming.
So, I tried to make frmExportSearchResultsProgress_Shown event as async/await but still operation is taking the same time as previous.
Can anyone please suggest me where I am doing wrong?
your frmExportSearchResultsProgress_Shown method starts on the UI thread
it then dispatches DoDataItemPrint to the ... same UI thread
it schedules a continuation (via await) so that when that incomplete thing happens, we get back into frmExportSearchResultsProgress_Shown, and since there's probably a sync-context in play here, the sync-context capture (implicit in await) would push us to ... the UI thread
As you can see: everything is happening on the UI thread.
If you want to not block the UI, you need to get off the UI thread. That could be as simple as using Task.Run to invoke DoDataItemPrint, but without knowing what that code contains, it is impossible to know whether you're using thread-bound controls to do the printing. If you are... it will be hard to get away from that.
There is documentation with definitions on what each enum does. But how am I able to demo/see this in practice? And how can I possibly know when to use which priority?
Here's some code I have created in attempt to see how the priorty affects the ordering, and it provides me with proof that the ordering is correct (the first loop iteration will have added a SystemIdle enum to the dispatch queue), but it still got added to the string last
private void btn_Click(object sender, RoutedEventArgs e)
{
StringBuilder result = new StringBuilder();
new Thread(() =>
{
var vals = Enum.GetValues(typeof(DispatcherPriority)).Cast<DispatcherPriority>().Where(y => y >= 0).ToList();
vals.Reverse();
vals.ForEach(x =>
{
Dispatcher.BeginInvoke(new Action(() =>
{
result.AppendLine(string.Format("Priority: {0} Enum:{1}", ((int)x), x.ToString()));
}), x);
});
}).Start();
ShowResultAsync(result, 2000);
}
private async void ShowResultAsync(StringBuilder s, int delay)
{
await Task.Delay(delay);
MessageBox.Show(s.ToString());
}
and the output order stays the same, even when the list is reversed (added this line just after vals gets assigned):
vals.Reverse();
So once again, is there anything more I can use when determining which dispatch priority I should assign?
In the Prism Framework the DefaultDispatcher which wraps Dispatcher uses a Normal priority. This should be the bread-and-butter for nearly all application scenarios.
/// <summary>
/// Wraps the Application Dispatcher.
/// </summary>
public class DefaultDispatcher : IDispatcherFacade
{
/// <summary>
/// Forwards the BeginInvoke to the current application's <see cref="Dispatcher"/>.
/// </summary>
/// <param name="method">Method to be invoked.</param>
/// <param name="arg">Arguments to pass to the invoked method.</param>
public void BeginInvoke(Delegate method, object arg)
{
if (Application.Current != null)
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, method, arg);
}
}
}
As long as you are not running any actual logic on the UI thread I would recommend doing this.
If you did for some reason want to run "quick" logic on the UI thread you could follow the advice here and stick with a value of Background.
I did look into it a little and I found some usages in NuGet's source where they use Send, Normal, Background and ApplicationIdle for various reasons but in my WPF development I have never had to fine tune usage of DispatcherPriority to this degree.
I've created a watchdog timer (using a System.Windows.Forms.Timer), which triggers if a long period of time expires without receiving a small packet of data:
using System.Windows.Forms;
public class Watchdog
{
private Timer Timer;
public void Go()
{
Timer.Start();
}
public void Reset()
{
Timer.Stop();
Timer.Start();
}
private void OnTimerExpired(object State)
{
Timer.Stop();
DoSomething();
}
public Watchdog()
{
Timer = new Timer();
Timer.Tick += new EventHandler(OnTimerExpired);
Timer.Interval = (1000 * Timeout);
}
}
The main code calls Go(), and then calls Reset() each time a packet is received. If the timer expires, OnTimerExpired() is called.
Since that there may be hundreds of packet receptions per second, and since the main job of the application is to respond to such packets, I'm beginning to wonder if resetting the timer isn't too CPU/OS intensive.
Any idea how calling Timer.Stop()/Timer.Start() this way may impact performance (in terms of latency)?
Use a simple timespan or integer variable as a flag. When the timer ticks, it checks against a Stopwatch object to see how much time has elapsed since the flag was last udpated. If it's longer than your timeout value you trigger your watchdog code.
Now, instead of resetting your timer, other code can just use the stopwatch to update your timespan flag value when a new packet comes in.
You should also either set your timer's tick interval to about 1/2 of what you want the actual timeout duration to be, or have code in the event to set your interval so your next tick event is just a few milliseconds after you would timeout if the connection was severed now. Otherwise you could end up waiting almost twice as long as the timeout duration in the situation where your last packet arrived very soon after a tick event.
Another option, by the way, is to just have a Boolean flag that's set whenever a message comes in. The timer event handler checks that flag and alerts if it's not set. So you have:
private bool GotAMessage = false;
void MessageReceived()
{
// happens whenever a message is received
GotAMessage = true;
}
void OnTimerExpired(object state)
{
if (!GotAMessage)
{
// didn't receive a message in time.
}
GotAMessage = false;
}
A simpler option is to call a method on the WatchDog class that updates a common lastPacketReceived value time a packet is received. Then you only need to start a single timer one time in the WatchDog class that ticks once per timeout interval and compares the current time to the lastPacketReceived value:
public static class WatchDog
{
static object locker = new object();
static long lastPacketReceived;
static Stopwatch stopWatch = new Stopwatch();
static long threshold = 5000;
static WatchDog()
{
Timer watchDogTimer = new Timer(1000);
watchDogTimer.Elapsed += new ElapsedEventHandler(watchDogTimer_Elapsed);
watchDogTimer.Start();
stopWatch.Start();
}
static void watchDogTimer_Elapsed(object sender, ElapsedEventArgs e)
{
lock (locker)
{
if ((stopWatch.ElapsedMilliseconds - lastPacketReceived) > threshold)
{
// threshold exceeded
}
}
}
public static void PacketReceived()
{
lock (locker)
{
lastPacketReceived = stopWatch.ElapsedMilliseconds;
}
}
}
Any idea how calling Timer.Stop()/Timer.Start()
This way may impact performance (in terms of latency)?
None
The amount of resources required to do this is unlikely to be measured. Unless you have a performance problem, don't try to solve a performance problem, at the very least use software to profile the software to see if its an actual problem.
There are times in my application, when I need to invoke my timer manually.
I've tried the following:
int originalInterval = t.Interval;
t.Interval = 0;
t.Interval = originalInterval;
but it wasn't consistent.
I've created a new timer, inheriting from System.Timers.Timer, and exposed a "Tick" method - but the problem was that the "Elapsed" event then fired synchronously.
When I implemented the "Tick" with a new Thread - the results were, again, not consistent.
Is there a better way to implement it?
I once had the same problem, so I used the AutoResetEvent to know if the Elapsed was invoked successfully:
/// <summary>
/// Tickable timer, allows you to manually raise a 'Tick' (asynchronously, of course)
/// </summary>
public class TickableTimer : System.Timers.Timer
{
public new event ElapsedEventHandler Elapsed;
private System.Threading.AutoResetEvent m_autoResetEvent = new System.Threading.AutoResetEvent(true);
public TickableTimer()
: this(100)
{
}
public TickableTimer(double interval)
: base(interval)
{
base.Elapsed += new ElapsedEventHandler(TickableTimer_Elapsed);
}
public void Tick()
{
new System.Threading.Thread(delegate(object sender)
{
Dictionary<string, object> args = new Dictionary<string, object>
{
{"signalTime", DateTime.Now},
};
TickableTimer_Elapsed(this, Mock.Create<ElapsedEventArgs>(args));
}).Start();
this.m_autoResetEvent.WaitOne();
}
void TickableTimer_Elapsed(object sender, ElapsedEventArgs e)
{
m_autoResetEvent.Set();
if (this.Elapsed != null)
this.Elapsed(sender, e);
}
}
It feels like you should look at your design a bit. Typically I try to avoid having the event handler method contain the actual work being done, but I rather try to let it be just a trigger, calling some other method that performs the work. That way you can invoke that other method from anywhere else as well:
private void Timer_Tick(object sender, EventArgs e)
{
new Thread(MethodThatDoesTheWork).Start();
}
private void MethodThatDoesTheWork()
{
// actual work goes here
}
Now, you can invoke MethodThatDoesTheWork from anywhere else within the class (either synchronously or asynchronously using a separate thread).
Alternatively, if MethodThatDoesTheWork should always be an asynchronous call, you can spawn the thread inside that method instead:
private void MethodThatDoesTheWork()
{
new Thread(() =>
{
// work code goes here
}).Start();
}
In these samples I have manually created threads. You can use that approach, the ThreadPool, Task or whatever other method of calling code asychronously, whichever fits best in your context.
Normally you shouldn’t need to fire a timer manually — you can always just run the event itself in a new thread. By and large, that’s basically what the timer does, and since you want to fire it manually, you don’t need the timer (for that manual invocation).
You didn’t specify any details as to what you mean by “not consistent”. The following should normally work:
Thread thread = new Thread(myDelegate);
thread.Start();
Of course, myDelegate can be a lambda in case you need to pass parameters:
Thread thread = new Thread(() => myMethod(param1, param2));
thread.Start();
I need some help on showing Progress bar upon loading data on my DataGridView. Any sample code?
Thanks.
regards,
kurt
Start the fetching of the data on another thread in order to not lock up the UI thread. You could expose a method on the UI (presume you have separation of layers here) and call that method from your business layer. Windows Form controls expose a InvokeRequired flag that you can use to check if you are calling the control from the correct thread. If you are not on the right thread you can call a delegate to do so.
/// <summary>
/// Delegate to notify UI thread of worker thread progress.
/// </summary>
/// <param name="total">The total to be downloaded.</param>
/// <param name="downloaded">The amount already downloaded.</param>
public delegate void UpdateProgressDelegate(int total, int downloaded);
/// <summary>
/// Updates the progress in a thread-safe manner.
/// </summary>
/// <param name="total">The total.</param>
/// <param name="downloaded">The downloaded.</param>
public void UpdateProgress(int total, int downloaded)
{
// Check we are on the right thread.
if (!this.InvokeRequired)
{
this.ProgressBar.Maximum = total;
this.ProgressBar.Value = downloaded;
}
else
{
if (this != null)
{
UpdateProgressDelegate updateProgress = new UpdateProgressDelegate(this.UpdateProgress);
// Executes a delegate on the thread that owns the control's underlying window handle.
this.Invoke(updateProgress, new object[] { total, downloaded });
}
}
}
Or you could just use a BackgroundWoker ;)