How do I build a timer that executes some code in intervals? - c#

I have an application where it is possible for the user to schedule some taske. A task could be to "send email", "execute application" etc. Each of these tasks has a start time, and this varies. Some of these tasks should run from the start time of the task to the stat time of the next task.
My question is how do i build a timer that will allow this to happen. Usually i would do this using a backgroundworker and an infinite loop - then check the time and the schedules each second or so. The problem with this approach is that when i close my application, the background worker is not closed.
Any ideas on a better pattern for this timer, or for solving the thread issue?

You can use your BackgroundWorker approach, but you have to correctly handle the application termination.
In the BackgroundWorker, you probably have something like:
while (true)
{
...
}
Try changing in
while (!myBackgroundWorker.CancellationPending)
{
...
}
and add something like
myBackgroundWorker.CancelAsync();
when the user quit your application.

Related

What happens when async code attempts to resume on a thread that is already executing?

I feel that the answer to this is due to me having an incorrect concept of how threads work, but here goes.
private void button1_Click(object sender, EventArgs e)
{
this.TestMethodAsync(); // No await, i.e. fire and forget
// ** Some code here to perform long running calculation (1) **
}
private async Task TestMethodAsync()
{
// Some synchronous stuff
await Task.Delay(1000);
// ** Some code here to perform long running calculation (2) **
}
First of all, I would not "fire and forget" an asynchronous method like this (I would use Task.Run) but I've come across code that does, and I'm trying to understand what the effect is.
In a WinForms application, which uses a WindowsFormsSynchronizationContext, my understanding of async and await tells me that when I click button1, the method will start synchronously on the UI thread. It will call TestMethodAsync and run synchronously until it reaches the await. It will then capture the context, start the Task.Delay task, and yield control to the caller. Since we are not awaiting this call, button1_Click will continue on the UI thread and start performing calculation (1).
At some point, Task.Delay(1000) will complete. A continuation will then run the remainder of the TestMethodAsync method using the captured context, which in this case means that the continuation will be run on the UI thread. This will now start performing calculation (2).
We now have two separate sections of code wanting to run on the same thread (the UI thread) at the same time. My investigations into this seem to suggest that the thread switches back and forth between the two sections of code in order to perform them both.
QUESTION:
I'm confused about exactly what is going on here. How is it possible to resume on a thread that is already running other code? What forces the thread to switch between the two sections of code that want to run? In general, what happens when you attempt to resume on a thread that is already running some other code?
(I suppose this isn't any different to how my click event runs on the UI thread in the first place, in as much as I know it runs on the UI thread, and I know the UI thread is also doing other stuff, but I've not really thought about it like this before.)
This is the secret that you do not understand: I give you the Windows Message Loop
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
BOOL bRet;
while(TRUE)
{
bRet = GetMessage(&msg, NULL, 0, 0);
if (bRet <= 0) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
This is the actual "main" of your application; you just don't see it because it is hidden behind the scenes.
A simpler loop could not be imagined. It gets a message from the queue. If there are no more messages then the program must be done. If there was a message then it runs the standard message translations and dispatches the message, and then keeps on running.
How is it possible to resume on a thread that is already running other code?
It isn't. "Resuming on a thread that is running other code" is actually putting a message in the queue. That "other code" is being synchronously called by DispatchMessage. When it is done, it returns to the loop, the queue is polled, and the message indicates what code needs to be dispatched next. That then runs synchronously until it returns back to the loop.
What forces the thread to switch between the two sections of code that want to run?
Nothing. That doesn't happen.
In general, what happens when you attempt to resume on a thread that is already running some other code?
The message that describes what continuation needs to be run is queued up.
I suppose this isn't any different to how my click event runs on the UI thread in the first place, in as much as I know it runs on the UI thread, and I know the UI thread is also doing other stuff, but I've not really thought about it like this before.
Start thinking about it.
Click events are exactly the same. Your program is doing something; you click the mouse; the click hander does not interrupt the UI thread and start running new work on it. Rather, the message is queued up, and when your UI thread control returns to the message loop, the click is eventually processed; DispatchMessage causes Button1_OnClick to be invoked via some mechanism in Windows Forms. That's what WinForms is; a mechanism for translating Windows messages into calls to C# methods.
But you already knew that. You know that when an event-driven program does a long-running synchronous operation, that the UI freezes, but that click events are processed eventually. How did you think that happened? You must have understood at some level that they were being queued up for processing later, right?
Exercise: What does DoEvents do?
Exercise: Given what you now know: what could possibly go wrong if you call DoEvents in a loop to unblock your UI?
Exercise: How is await different from DoEvents in a GUI application?
How is it possible to resume on a thread that is already running other code?
It needs to be specifically designed to support it. There needs to be some framework in place that allows the thread to take in work and to then execute that work at some later point in time.
This is how your UI thread works. It has a queue, and whenever you schedule work to be done in the UI thread you add an item to the end of the queue. The UI thread then takes the first item from the queue, executes it, and then when it's done, goes on to the next item, and so on, until you end your application.
What forces the thread to switch between the two sections of code that want to run?
Nothing, because it doesn't do that. It runs one, then when it finishes, it runs the other.
In general, what happens when you attempt to resume on a thread that is already running some other code?
Either someone wrote some custom code to specifically do just that, in which case, it does whatever that code specifically told it to do, or else you can't.

Stop a thread if it takes too long

I am new in Windows Phone development and I am trying to create a windows phone app using C#
Thread t = new Thread(doaheavywork);
t.Start();
if (!t.Join(1000)) // give the operation 1s to complete
{
t.Abort();
}
I cannot alter the doaheavywork function.
I just need the result to be omputed within 1 or 2 seconds, since sometimes it may run for very long time.
I have read using abort is the wrong way.
I am using the above in a PhotoChooserTask complete function. First run executes fine. That is, when I click the button to select a photo, the doaheavywork function doesn't exceed 1 sec. But if I try for the second time, the PhotoChooserTask just throws an exception and stops.
Is it because I aborted the process in 1st run? Or anything else? Is there any other way to do it?
.Abort() causes the thread to be destroyed completely. If you are generating a new thread each time like in your example, then it will work. However if you are using the same t object, then you need to create a new thread object, you can't run .Start() on an aborted thread.
However the fact you are aborting a thread is a concern. What happens with the application when it does take more than 2 seconds. Should you be showing the user, please wait, its taking longer than expected. Doing that in the if block is where to do it. .Join() won't stop the thread even if it doesn't manage to join.
Edit
You have 2 options you might want to consider in rewriting this section:
BackgroundWorker - http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx
Thread Task - http://msdn.microsoft.com/en-us/library/windowsphone/develop/cc221403(v=vs.105).aspx
Tasks seem to be the appropriate solution in your scenario.
One approach maybe be to consider using a Task and having a CancellationToken passed in to it from a CancellationTokenSource instantiated against a specific timespan - 2 seconds. That way when the the time specified has elapsed, the CancellationToken, passed to the Task, will be signaled and then appropriate action can be taken.

Proper way to delay code execution in a background worker

Ok so I've been reading up on Thread.Sleep, Task.Delay, AutoResetEvent ...etc
I see lots of arguments over which to use as it depends on the task being performed.
I currently use Thread.Sleep in everything and think I need to start avoiding it and use a better practice.
It's a client side app that contains a BackgroundWorker. The worker runs once every 30 minutes to check for updated data from a web service.
It then updates 3 int vars located in MainWindow. These don't do anything with the UI. They are just used in checks for other workers that are running.
Is one way to delay better than another?
If a user exit's the application and I'm calling Application.Current.Shutdown(), will it continue to run until Thread.Sleep has finished or will it exit even if a thread is sleeping?
use a combination of Task, await and CancellationTokenSource to be able to run in background, wait without wasting a thread, and cancel.
Something like:
var cancel = new CancellationTokenSource();
App.OnShutdown += (s,e) => cancel.Cancel();
await Task.Delay(1000,cancel.Token);

c# sleeping thread problem

what is the problem in the code part below? Any ideas? I m sending command to my device through serial port. After each command the device will work for this command and then the other command comes for it and continues like this.
in Button Click event
{
function1();
Thread.Sleep(5000);
function2();
Thread.Sleep(5000);
function3();
}
I figured out if i erase second sleep and function3 from the code like below, it does both two function but if i want to continue like this way it does not do the third one.
in Button Click event
{
function1();
Thread.Sleep(5000);
function2();
}
works...
Thank you
You're blocking the UI thread. Don't do that. It means your UI can't update itself. Instead, set a System.Windows.Forms.Timer to fire in 5 seconds with the next function to call. Alternatively, do all of this in a different thread entirely (possibly using Sleep, possibly using another kind of timer to fire on a thread-pool thread) and use Control.Invoke/BeginInvoke to marshall back to the UI thread when you need to update the UI itself.
EDIT: Given your "answer", it seems that blocking the UI thread was only one of the problems - and getting the device to respond properly at all is a bigger problem. You shouldn't just rely on sleeping for a certain amount of time. You should detect when the device has completed the previous command. It's possible that it doesn't give any feedback, but that would be horrifically poor design. If at all possible, investigate how to read feedback from the device as to when it's finished (e.g. reading from the serial port!) and only start the next command when the previous one has finished. Depending on how you receive the feedback, you could use a blocking call on a non-UI thread, or use an asynchronous model to trigger things.
The BackgroundWorker might be a solution to solve the blocking of the UI.
Get rid of the Sleeps If the functions are creating their own threads, give them callback methods that trigger the next function after the first has finished.
As the code is presented there it is nothing wrong with it. It will:
Execute function 1
Sleep 5 seconds
Execute function 2
Sleep 5 seconds
Execute function 3
However since this is on a GUI event it will freeze the application while doing so. Consider spinning off the execution into a thread instead.
In .Net 4.0:
Task.Factory.StartNew(() => sendData());
In all .Net versions:
System.Threading.Thread myThread = new System.Threading.Thread(sendData);
myThread.IsBackground = true;
myThread.Start();
And then you have your sendData method:
private void sendData()
{
function1();
Thread.Sleep(5000);
function2();
Thread.Sleep(5000);
function3();
}
If you really need to do stuff in the GUI thread you can make it more responsive by regularly calling Application.DoEvents();, but this is not a good way of solving it.
Also remember that you can't access the GUI from other threads. See http://kristofverbiest.blogspot.com/2007/02/simple-pattern-to-invoke-gui-from.html for sample code on how to invoke the GUI thread from other threads.
Thank you guys. I solve it. The problem is i did not make thread sleep enough. 5000 ms do not enough for the second command.

Displaying a "Please Wait" Dialog for a Non-Thread Safe task

I am using 3rd party library and some of the functions of the library take a long time to execute so I want to display a "Please Wait" dialog while the functions are busy.
Normally I would do something like this:
Thread longTask = new Thread (new ThreadStart(LongTask));
longTask.IsBackgroud = true;
longTask.Start();
pleaseWaitForm = new PleasWaitForm ("Please wait for task to complete");
pleaseWaitForm.ShowDialog();
void LongTask()
{
// Do time consuming work here
pleaseWaitForm.CanCloseFlag = true;
}
Unfortunately the 3rd party library is not thread-safe. Any workarounds? Is there any way of managing the Dialog Box as a background task?
I think you are misunderstanding what "thread safe" means. If you are going to be calling methods/properties of your 3rd party component only from single thread, the component does not have to be thread safe. See this article.
Furthermore, I would suggest you use a background worker class in this case.
HTH
You pretty much need to build your own dialog box.
One option is to poll your completed flag in a timer or the like.
Yet another option is to let the form "own" the task and use a BackgroundWorker for progress and completion notification.
Suppose you have a method, LongTask, and it is not thread safe. If that method is running and it does not need any shared variables, then you can simply wrap it around a BackgroundWorker and update the "please wait" screen the moment the task finishes.
If a certain method is not thread safe, that can still mean it is safe to use it in a thread, it just depends whether it runs multiple times asynchronously (danger!) or synchronously (not a problem).

Categories

Resources