async/await thread transition curiosity - task-parallel-library

I have the following simple console application:
class Program
{
private static int times = 0;
static void Main(string[] args)
{
Console.WriteLine("Start {0}", Thread.CurrentThread.ManagedThreadId);
var task = DoSomething();
task.Wait();
Console.WriteLine("End {0}", Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
static async Task<bool> DoSomething()
{
times++;
if (times >= 3)
{
return true;
}
Console.WriteLine("DoSomething-1 sleeping {0}", Thread.CurrentThread.ManagedThreadId);
await Task.Run(() =>
{
Console.WriteLine("DoSomething-1 sleep {0}", Thread.CurrentThread.ManagedThreadId);
Task.Yield();
});
Console.WriteLine("DoSomething-1 awake {0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("DoSomething-2 sleeping {0}", Thread.CurrentThread.ManagedThreadId);
await Task.Run(() =>
{
Console.WriteLine("DoSomething-2 sleep {0}", Thread.CurrentThread.ManagedThreadId);
Task.Yield();
});
Console.WriteLine("DoSomething-2 awake {0}", Thread.CurrentThread.ManagedThreadId);
bool b = await DoSomething();
return b;
}
}
with the output
Start 1
DoSomething-1 sleeping 1
DoSomething-1 sleep 3
DoSomething-1 awake 4
DoSomething-2 sleeping 4
DoSomething-2 sleep 4
DoSomething-2 awake 4
DoSomething-1 sleeping 4
DoSomething-1 sleep 3
DoSomething-1 awake 3
DoSomething-2 sleeping 3
DoSomething-2 sleep 3
DoSomething-2 awake 3
End 1
I'm aware that console apps don't provide a SynchronizationContext so Tasks run on the thread pool. But what surprises me is that when resuming execution from an await in DoSomething, we are on the same thread as we are on inside the await. I had assumed that we'd either return to the thread we awaited on or be on another thread entirely when we resume execution of the awaiting method.
Does anyone know why? Is my example flawed in some way?

This behavior is due to an optimization (which is an implementation detail).
Specifically, the continuation scheduled by await uses the TaskContinuationOptions.ExecuteSynchronously flag. This is not officially documented anywhere but I did encounter this a few months ago and wrote it up on my blog.
Stephen Toub has a blog post that is the best documentation on how ExecuteSynchronously actually works. One important point is that ExecuteSynchronously will not actually execute synchronously if the task scheduler for that continuation is not compatible with the current thread.
As you pointed out, console apps don't have a SynchronizationContext, so task continuations scheduled by await will use TaskScheduler.Current (which in this case is TaskScheduler.Default, the thread pool task scheduler).
When you start another task via Task.Run, you're explicitly executing it on the thread pool. So when it reaches the end of its method, it completes its returned task, causing the continuation to execute (synchronously). Since the task scheduler captured by await was the thread pool scheduler (and therefore compatible with the continuation), it will just directly execute the next portion of DoSomething.
Note that there is a race condition here. The next portion of DoSomething will only execute synchronously if it is already attached as a continuation to the task returned by Task.Run. On my machine, the first Task.Run will resume DoSomething on another thread because the continuation is not attached by the time the Task.Run delegate completes; the second Task.Run does resume DoSomething on the same thread.
So I modified the code to be slightly more deterministic; this code:
static Task DoSomething()
{
return Task.Run(async () =>
{
Console.WriteLine("DoSomething-1 sleeping {0}", Thread.CurrentThread.ManagedThreadId);
await Task.Run(() =>
{
Console.WriteLine("DoSomething-1 sleep {0}", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(100);
});
Console.WriteLine("DoSomething-1 awake {0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("DoSomething-2 sleeping {0}", Thread.CurrentThread.ManagedThreadId);
var task = Task.Run(() =>
{
Console.WriteLine("DoSomething-2 sleep {0}", Thread.CurrentThread.ManagedThreadId);
});
Thread.Sleep(100);
await task;
Console.WriteLine("DoSomething-2 awake {0}", Thread.CurrentThread.ManagedThreadId);
});
}
(on my machine) shows both of the possibilities from the race condition:
Start 8
DoSomething-1 sleeping 9
DoSomething-1 sleep 10
DoSomething-1 awake 10
DoSomething-2 sleeping 10
DoSomething-2 sleep 11
DoSomething-2 awake 10
End 8
BTW, your use of Task.Yield is incorrect; you have to await the result to actually do anything.
Note that this behavior (await using ExecuteSynchronously) is an undocumented implementation detail and may change in the future.

When you're not specifying which scheduler to use, you're at the whim of "the system" to decide where/how to run your tasks. All that await really does is to place all of the code following the awaited task into a continuation task that runs after the awaited task completes. In many cases, the scheduler will say "hey, I just finished a task on thread X, and there's a continuation task as well... since thread X is done, I'll just re-use it for the continuation!" This is exactly the behavior you're seeing. (See http://msdn.microsoft.com/en-US/library/vstudio/hh156528.aspx for more details.)
If you manually create your continuations (rather than letting await do so for you), you can have more control about exactly how and where the continuation runs. (See http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskcontinuationoptions.aspx for the continuation options you can pass to Task.ContinueWith().)

Related

When is a windows service considered "started"

We have a process that is executed as a windows service,
This process serves as an interface server processing incoming messages, transforms them and sends them out to another interface.
it is a rather heavy process, it needs to load a lot of things into memory and that takes some time (few minutes).
due to its nature, when we start it using its windows service, it remains in "starting" status for a very long time (sometimes more than 20 minutes)
even when we can see the process already works and process messages just fine (going by its logs).
so the question is - when is a service considered "starting" and when is it considered "started"? based on what factors?
Starting status finish when onstart is completed.
You should write starting code after onstart event.
puclic class Service1
{
private Timer timer = new Timer();
protected override void OnStart(string[] args)
{
this.timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
this.timer.Interval = 1 * 1000; // 1 second
this.timer.Enabled = true;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
this.timer.Enabled = false; // OnElapsedTime run only one time
// Write your code
}
}

Spring State Machine task execution not firing

I am having issues with getting a runnable to run in the manner described in the following reference:
http://docs.spring.io/autorepo/docs/spring-statemachine/1.0.0.M3/reference/htmlsingle/#statemachine-examples-tasks
TasksHandler handler = TasksHandler.builder()
.task("1", sleepRunnable())
.task("2", sleepRunnable())
.task("3", sleepRunnable())
.build();
handler.runTasks();
My implementation looks like this:
private Action<States, Events> getUnlockedAction() {
return new Action() {
#Override
public void execute(StateContext sc) {
System.out.println("in action..");
handler = new TasksHandler.Builder().taskExecutor(taskExecutor()).task("1", dp.runProcess(1)).build();
handler.addTasksListener(new MyTasksListener());
handler.runTasks();
System.out.println("after action..");
}
};
}
The initialization for the TaskExecutor looks like this:
#Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor te = new ThreadPoolTaskExecutor();
te.setMaxPoolSize(50);
te.setThreadNamePrefix("LULExecutor-");
te.setCorePoolSize(25);
te.initialize();
return te;
}
My code for dp (DataProcessor) looks like this:
#Component
#Qualifier("dataProcessor")
public class ADataProcessor {
public Runnable runProcess(final int i) {
return new Runnable() {
#Async
#Override
public void run() {
long delay = (long) ((Math.random() * 10) + 1) * 1000;
System.out.println("In thread " + i + "... sleep for " + delay);
try {
Thread.sleep(delay);
} catch (InterruptedException ex) {
Logger.getLogger(FSMFactoryConfig.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("After thread " + i + "...");
}
};
}
}
When i execute my code, I see the messages for 'in action..' and 'after action..' with no delay..
When I use the following:
taskExecutor().execute(dp.runProcess(1));
taskExecutor().execute(dp.runProcess(2));
taskExecutor().execute(dp.runProcess(3));
taskExecutor().execute(dp.runProcess(4));
taskExecutor().execute(dp.runProcess(5));
taskExecutor().execute(dp.runProcess(6));
I get what I would expect from using the TasksHandler..
state changed to UNLOCKED
In thread 2... sleep for 10000
In thread 3... sleep for 5000
In thread 4... sleep for 8000
In thread 5... sleep for 4000
In thread 6... sleep for 4000
In thread 1... sleep for 9000
Jan 13, 2016 12:32:13 PM - org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor initialize
INFO: Initializing ExecutorService
state changed to LOCKED
After thread 5...
After thread 6...
After thread 3...
After thread 4...
After thread 1...
After thread 2...
None of the messages before or after the delay in the sleep are displayed when using the TasksHandler. So my question, how do I actually execute my runnable?? If I'm doing it correctly, what should I check?
I think you've slightly misunderstood few things. First you're linking to tasks sample having the original idea which were turned into a tasks recipe. It's also worth to look unit tests for tasks.
You register runnables with taskhandler get a state machine from it to start it and then tell handler to run tasks.
I now realize that in docs I probably should be bit more clear of its usage.
After adding all tasks to the handler, I had to start the state machine before invoking runTasks().
handler.getStateMachine().startReactively().block();
handler.runTasks();

How to hit the breakpoint at catch block when working with TPL

As I started understanding thru the TPL. I got stuck over in this code. I have 2 task. Task1 thows ArgumentOutOfRangeException and Task2 throws NullReferenceException.
Consider this below code:
static void Main(string[] args) {
// create the cancellation token source and the token
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
// create a task that waits on the cancellation token
Task task1 = new Task(() => {
// wait forever or until the token is cancelled
token.WaitHandle.WaitOne(-1);
// throw an exception to acknowledge the cancellation
throw new OperationCanceledException(token);
}, token);
// create a task that throws an exceptiono
Task task2 = new Task(() => {
throw new NullReferenceException();
});
// start the tasks
task1.Start(); task2.Start();
// cancel the token
tokenSource.Cancel();
// wait on the tasks and catch any exceptions
try {
Task.WaitAll(task1, task2);
} catch (AggregateException ex) {
// iterate through the inner exceptions using
// the handle method
ex.Handle((inner) => {
if (inner is OperationCanceledException) {
// ...handle task cancellation...
return true;
} else {
// this is an exception we don't know how
// to handle, so return false
return false;
}
});
}
// wait for input before exiting
Console.WriteLine("Main method complete. Press enter to finish.");
Console.ReadLine();
}
I have put the try catch block for Task.WaitAll(task1, task2). It should ideally hit the breakpoint in ex.handler statement inside Catch block. As I understand that whatever may be the result it should hit the catch block.
Same case is happening if I have task1.Result/task2.Result.
My Question is: In debug mode why isn't the breakpoint being hit at the catch block when I am intentionally throwing it from task as I want to examine the statements under catch block. It just puts yellow mark at saying "NullReferenceException unhandled by the user code".
Task task2 = new Task(() => {
throw new NullReferenceException();
});
How do I hit the break point at catch block???
Thanks for replying :)
As Arne Claassen explained in their comment, the debugger pauses execution at the point the original exception is thrown because the thread does not handle the exception. If you continue exceution (F5 or play button), the program should continue to the point where you are handling the exception in your continuation.

Easy way to excecute method after a given delay?

Is there a easy way to perform a method after a given delay like in iOS out of the box?
On iPhone I would do this:
[self performSelector:#selector(connectSensor) withObject:nil afterDelay:2.5];
It will then schedule the method connectSensor on the main thread (UI thread) to be executed after 2,5 seconds. And because it is automatically scheduled on the main thread, you don't have to worry about cross thread issues. (There is also a performSelectorOnBackground version)
So how would I do this properly in WP7?
Currently I'm accomplishing this with a timer, but I'm not sure if this is a good solution.
private Timer timer;
private void DoSomethingAfterDaly()
{
// ... do something here
timer = new Timer( (o) => Deployment.Current.Dispatcher.BeginInvoke(() => NavigationService.GoBack()), null, 2500, Timeout.Infinite);
}
How could this be encapsulated into an extension method so I can just call this.Perform(MyMethod, null, 2500); ?
You can use a BackgroundWorker like so:
private void Perform(Action myMethod, int delayInMilliseconds)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (s, e) => Thread.Sleep(delayInMilliseconds);
worker.RunWorkerCompleted += (s, e) => myMethod.Invoke();
worker.RunWorkerAsync();
}
The call into this method would look like this:
this.Perform(() => MyMethod(), 2500);
The background worker will run the sleep on a thread off of the UI thread so your application is free to do other things while the delay is occurring.
You can use the Reactive Extensions for WP7 to observe on a timer:
Observable
.Timer(TimeSpan.FromMilliseconds(2500))
.SubscribeOnDispatcher()
.Subscribe(_ =>
{
NavigationService.GoBack();
});
Given the brevity of this code, I don't think you'd gain much by creating an extension method for it :) For more information about the Reactive Extensions for WP7, take a look at this MSDN page
.

How to make a Windows Service terminate when one of its sub-threads terminate

in the ServiceStart() call of a windows service, I create a thread and start it.
Thread1 = New TThread1(false)
In the Execute procedure of the subthread, there is a loop that runs forever and does that the service is supposed to do.
The problem is that when I get an error in this thread, I want to terminate the thread, and stop the service too.
How can I get the service to stop itself if a thread that it has started stops (fails).
A possibility is to use watchdog timers:
in your thread you reset the timer (eg. every time you enter the loop).
when interval of timer is expired, you know that the thread is probably not working anymore, so you can restart the service or what ever...
A better approach might be to catch exceptions in the thread and log them. Or you could catch the exception, log it, then stop the service. That way you are in control of the service stopping and you also have some insight into the errors being generated.
make a call to stop service :
bool StopService(string svr_name)
{
bool ret = false;
if (svr_name.Length > 0)
{
try
{
ServiceController sc = new ServiceController(svr_name);
if (sc.Status == ServiceControllerStatus.Stopped)
{
return true;
}
sc.Stop();
}
catch (Exception)
{
return false;
}
}
return ret;
}

Resources