I want to call a task at a specified interval. And avoid calling a new task unless the last has already completed.
private async void OnTimerTick(object sender, object e)
{
if (_criticalSection.IsEntered()) return; // only allow 1 at any given time, ignore the rest
using (var section = await _criticalSection.EnterAsync())
{
await update();
}
}
How do I achieve this? Any suggestions for a better pattern?
A critical section (like a Window's mutex) is for mutual exclusion: only allowing a single thread into a code path.
But that's not what you are trying to do: you need something that will tell you if something is happening.
A better approach would be a Manual Reset Event: set it (also know as signalled) at the start of the task and reset at the end. Then you can check if it is signalled by waiting on it with a timeout of zero for a normal Window's event, or with the applicable member for other types of event.
As this appears to be all in a single process a good starting point is System.Threading.ManualRestEventSlim. Used something like:
// One off initialisation somewhere at class scope
private static ManualResetEventSlim taskRunning = new ManualResetEventSlim();
private static object taskLock = new Object();
// code called from the timer, do in a lock to avoid race conditions with two
// or more threads call this.
lock (taskLock) {
if (!taskRunning.IsSet) {
StartTheTask(); // assuming this does not return until task is running.
}
}
// At the outermost scope of the code in the task:
try {
Debug.Assert(!taskRunning.IsSet); // Paranoia is good when doing threading
taskRunning.Set();
// Task impementation
} finally {
Debug.Assert(taskRunning.IsSet); // Paranoia is good when doing threading
taskRunning.Reset();
}
Another approach would be to always start the task, but have it check the event, if set then immediately exit. This would still need the lock to avoid races between the IsSet and Set() calls across threads. This second approach keeps the checking code together at the cost of briefly having another task running (unless that is common I would likely take this approach for the code locality).
Related
I need to do something like the following code. Note, this does not work due to the nature of locks in .Net (which I'll address after the code) but I need some form of implementation like this that works, but I don't know what to do.
static object lockMethod = new object();
static object lockTask = new object();
public static string testLocksAndTasks()
{
//This method is fast executing code but to prevent other issues, I
//lock this method. This might be impertinent to the base need of this
//question, but since I do use a lock on the entire requesting method, I
//put it here. This is because I integrate some logging and a bit of
//other logic on static variables so I just lock the method. This entire
//function is fast. The really slow code is in
//DoWorkInOtherThreadMethod(), which is why it needs to run in a
//background task.
lock (lockMethod)
{
if (Monitor.TryEnter(lockTask))
{
Task.Run(DoWorkInOtherThreadMethod)
.ContinueWith(ct=>
Monitor.Exit(lockTask)); //Oop! Unlocking on separate task NOT ALLOWED!
return "We locked lockTask and started the thread!";
}
else return "Task called and executed by other request!";
}
}
The above code gets the point across for what I'm trying to accomplish. I need to have a method (that is executed from a web request) and I need to test if a launched task from the request is already running in another thread. If it isn't running, I need to create the lock for the task (lockTask in this example) and prevent future calls while it runs, and report ack to the caller the state of the background task. If the lockTask is already in use, I specifically need to return "Task X is already running for Y item". (Note, I didn't include that extra information for what's already running, but that's not difficult to do and not required for this example.)
My code could theoretically work because once the entire task is finished, the call to ContinueWith() would unlock the lock for the task. However, what I've found is that this throws errors because the initial lock on lockTask is created in one thread, and then the subsequent unlock with Monitor.Exit(lockTask) is occurring on another thread and that's not allowed.
I could try to restructure my code to some thing like the code provided below, but this also has issues for my needs.
public static string testLocksAndTasks()
{
lock (lockMethod)
{
//Check if we're locked!
if (!Monitor.IsEntered(lockTask))
{
Task.Run(()=>
{
//We weren't locked, so TryEnter...
if (Monitor.TryEnter(lockTask))
{
DoWorkInOtherThreadMethod();
Monitor.Exit(lockTask); //NOTE: I KNOW THIS SHOULD BE WRAPPED IN A
//TRY/CATCH/FINALLY. I'm just keeping sample
//the code simple.
}
else
{
//Oh no! This is actually quite possible, but this is a case I never
//want to reach?! I can't report this back to the initial call to
//testLocksAndTasks since we are in a new thread!
}
});
return "We locked lockTask and started the thread!";
}
else return "Task called and executed by other request!";
}
}
My comment above outlines the obvious problem. I can create my task lock within the task and this fixes the first issue with the lock and exits happening on separate threads. However, this introduces a different but still important issue.
Since this code can execute semi-simultaneously across multiple request threads, there is a chance that there might be multiple calls to !Monitor.IsEntered(lockTask) returning true because the lock is not set until the Monitor.TryEnter(...) request is made within a new task. This wouldn't be an issue, however, I now can't return a proper state response to testLocksAndTasks().
How can I properly implement something like this where I lock a long running task but can also report if it's running?
Sounds like you don't need a lock but a simple flag indicating whether task is running. Now to read and set this flag you can use regular lock. So you check the flag and start the task if necessary inside the lock. When task is done you again set the flag inside the lock. Sample code:
static object lockTask = new object();
private static bool taskRunning = false;
public static string testLocksAndTasks()
{
lock (lockTask)
{
// check inside the lock
if (!taskRunning)
{
Task.Run(DoWorkInOtherThreadMethod)
.ContinueWith(ct =>
{
lock (lockTask)
{
// reset flag inside the lock
taskRunning = false;
}
});
// start task and set the flag
taskRunning = true;
return "We locked lockTask and started the thread!";
}
else return "Task called and executed by other request!";
}
}
I am trying to get the proper 'structure' for monitoring the state of a game from external source(s) using (Tasks) async/await in order to run the tasks in an infinite loop, however the current way its written seems to just freeze up my UI.
What I have so far:
(in the "state machine" class)
// Start monitoring the game state for changes
public void Start()
{
tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
IsRunning = true;
task = Task.Factory.StartNew(async () =>
{
while (true)
{
await Task.Run(()=>CheckForStateChange());
await Task.Delay(1000); // Pause 1 second before checking state again
}
}, token, TaskCreationOptions.LongRunning, TaskScheduler.FromCurrentSynchronizationContext());
}
Without the above "Task.Delay" line the UI completely freezes up. With the "Task.Delay" line it doesn't freeze up, but if I try to drag the window it skips back to where I began dragging it.
My assumption with the current code is that the 'await Task.Run()' executes and upon completion the 'await Task.Delay()' executes and then on completion returns to the beginning of the while(true) infinite loop. (ie. not running in parallel).
The CheckForStateChange() signature is as follows:
private void CheckForStateChange()
{
// ... A bunch of code to determine and update the current state value of the object
}
Nothing special there, simple non-async method. I have read through lots of examples / questions here on StackOverflow and I used to have CheckForStateChange as returning a Task (with awaitable actions inside the method) and many other iterations of code (with the same results).
Finally I call the Start() method from the main win32 form (button) as follows:
private void btnStartSW_Click(object sender, EventArgs e)
{
// Start the subscription of the event handler
if(!state.IsRunning)
{
state.StateChange += new SummonersWar.StateChangeHandler(OnGameStateChange);
state.Start();
}
}
I think the above code is the simplest form I have written the code structure in so far, but apparently its still not written 'properly'. Any help would be appreciated.
UPDATE:
The publisher side (state machine class):
// ------ Publisher of the event ---
public delegate void StateChangeHandler(string stateText);
public event StateChangeHandler StateChange;
protected void OnStateChange() // TODO pass text?
{
if (StateChange != null)
StateChange(StateText());
}
Where the StateText() method is just a temporary way of retrieving a 'text' representation of the current state (and is really a placeholder at this point until I organize it into a tidier struct)
IsRunning is purely a public bool.
And the handler in the UI thread:
private void OnGameStateChange(string stateText)
{
// Game State Changed (update the status bar)
labelGameState.Text = "State: " + stateText;
}
Why the UI freezes
In terms of the main question: you're already calling your CheckForStateChange via Task.Run, so there is no way that your CheckForStateChange will freeze the UI unless it includes calls which are marshalled back to the UI thread (i.e. Control.Invoke or SynchronizationContext.Post/Send used explicitly, or implicitly via a Task started on the UI TaskScheduler).
The best place to start looking is your StateChange handlers (i.e. StateChangeHandler). Also have a look at where the StateChange event is raised. You'll find thread marshalling code at one of these sites.
Other issues
You're passing the TaskScheduler pointing to the UI SynchronizationContext to the outer task. You're also passing in TaskCreationOptions.LongRunning. In simple terms you're telling the task factory to "start a task on a dedicated thread, and on the current thread". These two are mutually exclusive requirements and you can pretty safely drop them both.
If, as a result of the above, your outer task happens to execute on the UI thread, it won't really trip you up as the inner call is wrapped in Task.Run, but this probably isn't the behaviour you expect.
You are storing the result of Task.Factory.StartNew inside a task field or property. Note, however, that your Task.Factory.StartNew call returns a Task<Task>, so the saved Task instance will transition to completed state almost immediately unless you call Unwrap on it and get to the inner task. To avoid this entire mess, just use Task.Run to create the outer task (as it has Unwrap semantics built in). If you do that, you can ditch the inner Task.Run completely, like so:
public bool IsRunning
{
get
{
return task.Status == TaskStatus.Running;
}
}
public void Start()
{
tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
task = Task.Run(async () =>
{
while (true)
{
CheckForStateChange(token);
token.ThrowIfCancellationRequested();
await Task.Delay(1000); // Pause 1 second before checking state again
}
}, token);
// Uncomment this and step through `CheckForStateChange`.
// When the execution hangs, you'll know what's causing the
// postbacks to the UI thread and *may* be able to take it out.
// task.Wait();
}
Since you have a CancellationToken you need to be passing it to CheckForStateChange, and checking it periodically - otherwise it only gets checked once, when the Task is started, and then never again.
Note that I have also provided a different IsRunning implementation. Volatile state is hard to get right. If the framework is giving it to you for free, you should use it.
Final word
Overall this entire solution feels like a bit of a crutch for something that should be done more reactively - but I can think of scenarios where this sort of design is valid. I'm just not convinced that yours is really one of them.
EDIT: how to find what's blocking the UI
I'll get downvoted to oblivion for this, but here goes:
The sure way to find what's causing postbacks to the UI thread is to deadlock with it. There's plenty of threads here on SO telling you how to avoid that, but in your case - we'll cause it on purpose and you'll know exactly what calls you need to avoid when you're polling for changes - although whether or not it will be possible to avoid these calls, remains to be seen.
I've put a task.Wait instruction at the end of my code snippet. Provided that you call Start on the UI thread, that should cause a deadlock with something inside your CheckForStateChange, and you will know what it is that you need to work around.
I sometimes encounter code in the following form:
while (true) {
//do something
Thread.Sleep(1000);
}
I was wondering if this is considered good or bad practice and if there are any alternatives.
Usually I "find" such code in the main-function of services.
I recently saw code in the "Run" function in a windows azure worker role which had the following form:
ClassXYZ xyz = new ClassXYZ(); //ClassXYZ creates separate Threads which execute code
while (true) {
Thread.Sleep(1000);
}
I assume there are better ways to prevent a service (or azure worker role) from exiting.
Does anyone have a suggestion for me?
Well when you do that with Thread.Sleep(1000), your processor wastes a tiny amount of time to wake up and do nothing.
You could do something similar with CancelationTokenSource.
When you call WaitOne(), it will wait until it receives a signal.
CancellationTokenSource cancelSource = new CancellationTokenSource();
public override void Run()
{
//do stuff
cancelSource.Token.WaitHandle.WaitOne();
}
public override void OnStop()
{
cancelSource.Cancel();
}
This will keep the Run() method from exiting without wasting your CPU time on busy waiting.
An alternative approach may be using an AutoResetEvent and instantiate it signaled by default.
public class Program
{
public static readonly AutoResetEvent ResetEvent = new AutoResetEvent(true);
public static void Main(string[] args)
{
Task.Factory.StartNew
(
() =>
{
// Imagine sleep is a long task which ends in 10 seconds
Thread.Sleep(10000);
// We release the whole AutoResetEvent
ResetEvent.Set();
}
);
// Once other thread sets the AutoResetEvent, the program ends
ResetEvent.WaitOne();
}
}
Is the so-called while(true) a bad practice?
Well, in fact, a literal true as while loop condition may be considered a bad practice, since it's an unbrekeable loop: I would always use a variable condition which may result in true or false.
When I would use a while loop or something like the AutoResetEvent approach?
When to use while loop...
...when you need to execute code while waiting the program to end.
When to use AutoResetEvent approach...
...when you just need to hold the main thread in order to prevent the program to end, but such main thread just needs to wait until some other thread requests a program exit.
If you see code like this...
while (true)
{
//do something
Thread.Sleep(1000);
}
It's most likely using Sleep() as a means of waiting for some event to occur — something like user input/interaction, a change in the file system (such as a file being created or modified in a folder, network or device event, etc. That would suggest using more appropriate tools:
If the code is waiting for a change in the file system, use a FileSystemWatcher.
If the code is waiting for a thread or process to complete, or a network event to occur, use the appropriate synchronization primitive and WaitOne(), WaitAny() or WaitAll() as appropriate. If you use an overload with a timeout in a loop, it gives you cancelability as well.
But without knowing the actual context, it's rather hard to say categorically that it's either good, bad or indifferent. If you've got a daemon running that has to poll on a regular basis (say an NTP client), a loop like that would make perfect sense (though the daemon would need some logic to monitor for shutdown events occuring.) And even with something like that, you could replace it with a scheduled task: a different, but not necessarily better, design.
If you use while(true) you have no programmatic means of ending the loop from outside the loop.
I'd prefer, at least, a while(mySingletonValue) which would allow us to switch the loop as needed.
An additional approach would be to remove the functional behavior from the looping behavior. Your loop my still be infinite but it calls a function defined elsewhere. Therefore the looping behavior is completely isolated to what is being executed by the loop:
while(GetMySingletonValue())
{
someFunction();
}
In this way your singleton controls the looping behavior entirely.
There are better ways to keep the Azure Service and exit when needed.
Refer:
http://magnusmartensson.com/howto-wait-in-a-workerrole-using-system-timers-timer-and-system-threading-eventwaithandle-over-system-threading-thread-sleep
http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/azure-worker-role-exiting-safely/
It really depends on that //do something on how it determines when to break out of the loop.
In general terms, more appropriate way to do it is to use some synchronization primitive (like ManualResetEvent) to wait on, and the code that processes and triggers the break of the loop (on the other thread) to signal on that primitive. This way you don't have thread wasting resources by being scheduled in every second to do nothing, and is a much cleaner way to do it.
I personally don't like Thread.Sleep code. Because it locks the main thread. You can write something like this, if it is a windows application besides it allows you more flexibility and you can call it async:
bool switchControl = true;
while (switchControl) {
//do something
await Wait(1);
}
async void Wait(int Seconds)
{
DateTime Tthen = DateTime.Now;
do
{
Application.DoEvents(); //Or something else or leave empty;
} while (Tthen.AddSeconds(Seconds) > DateTime.Now);
}
I'm working on a Windows 8.1 store app in which the user can save text to a file.
I've been trying to understand how to best use async and await.
This is what I've come up with:
private async void userText_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
if (addUserImput)
{
userStringlist.Add(userBox.Text);
userBox.Text = "";
addUserImput = false;
}
await WriteToFileAsync();
addUserImput = true;
}
}
And the async-method looks like this:
private async Task WriteToFileAsync()
{
string name = "userStrings.txt";
var option = CreationCollisionOption.ReplaceExisting;
var folder = Windows.Storage.ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync(name, option);
await Windows.Storage.FileIO.WriteLinesAsync(file, userStringlist);
}
As soon as WriteToFileAsync reaches the await-keyword the execution will start over. In order to prevent duplicates in my list I had to add the if-statement.
It just strikes me as odd. I'm still new to this, so I might've missed something. Why does the keydown event resume from the top, doing work that has already been done?
My "workaround" works, I just don't get the logic behind the event's behaviour.
Yes, that's how asynchronous solutions work. When you hit your first actually asynchronous operation (in this case, CreateFileAsync) the method returns to its caller, which returns to its caller, and it eventually works it's way out of the entire method and back up to your application's message loop. It then continues on processing other UI messages. Some of those messages may be key down events (and they could end up being run before your asynchronous operation is completed). Other events could be things like paint events or mouse click events that lets your form do whatever it needs to interact with the user. This is what prevents it from freezing.
What you want to do is to prevent the given section of code that you have from being run concurrently. If this weren't asynchronous this is something that you would generally solve using the lock keyword, but that isn't an option for an asynchronous method. What you need is some method of preventing access to the code until any other executions of that code block finish. Fortunately there are tools available to do this. You could use a boolean, as you are, but this is somewhat fragile and fairly easy to make a mistake with as the complexity of the application grows. A Semaphore is specifically designed for this task:
private SemaphoreSlim semaphore = new SemaphoreSlim(1);
private async void Bar()
{
try
{
await semaphore.WaitAsync();
//do stuff
}
finally
{
semaphore.Release();
}
}
The SemaphoreSlim class has a WaitAsync method specifically designed for use in asynchronous methods, such as yours. You can wait until the semaphore is free, do your code, and then ensure that you release the semaphore when done so that other code can then move into the code block.
You may need to use handled = true in this case . check if http://msdn.microsoft.com/en-us/library/system.windows.forms.keyeventargs.handled(v=vs.110).aspx works
I have this code:
Thread t = new Thread(() => UpdateImage(origin));
t.Name = "UpdateImageThread";
t.Start();
This code is created on a Custom Control. I want to stop this thread (if it's running) when the object is going to be dispose.
This custom control has the following method:
void IDisposable.Dispose()
{
/* My own code */
base.Dispose(true);
}
I think this is the place to put the code but:
How can I know is the thread is running?
How can I take a referece for the thread and stop it?
By the way, UpdateImage call a web service, so I think that it's waiting all of its life.
How can I finish this wait?
Thank you!
It depends a lot on what UpdateImage() does and how well it copes with the Image being disposed while it it still active. If UpdateImage() is your code and contains a loop you can tell it to stop (using a field like _stopping). If not, the best thing may be to do nothing - in the rare case of Disposing the control while the image is still updating you take the penalty of leaving it to the GC.
About how to get the Thread: By saving the reference when and where you create it, for instance int the private member _updateThread.
Now actually stopping (aborting) the thread is a (very) bad idea.
So you'll need an indicator, like
private bool _stopping = false;
And it is up to the UpdateImage() method to react to _stopping == true and stop with what it is doing.
Your Dispose() can then use
_stopping = true;
_updateThread.Join()
Save your thread variable 't' so that you can re-use it later.
Within your Dispose method you want something like:
void IDisposable.Dispose()
{
if(t.IsRunning)
{
cancelThreads = true; // Set some cancel signal that the thread should check to determine the end
t.Join(500); // wait for the thread to tidy itself up
t.Abort(); // abort the thread if its not finished
}
base.Dispose(true);
}
You should be careful aborting threads though, ensure that you place critical section of code within regions that won't allow the thread to stop before it has finished, and catch ThreadAbortExceptions to tidy anything up if it is aborted.
You can do something like this in the threads start method
public void DoWork()
{
try
{
while(!cancelThreads)
{
// Do general work
Thread.BeginCriticalRegion();
// Do Important Work
Thread.EndCriticalRegion();
}
}
catch(ThreadAbortException)
{
// Tidy any nastiness that occured killing thread early
}
}
I suggest to override the Dispose method in your Custom Control.
There you have the reference of your thread and you can call .Join() for example...