I have created an asynchronous Task that the user can pause / resume. When the task is first run, it appears to run under a new thread (Thread.CurrentThread.ManagedThreadId == 5), which is separate from the main UI thread (Thread.CurrentThread.ManagedThreadId == 1). However, when the Task is paused (via an await method within the tasks main while() loop), the debug window shows the message: "Thread finished: #3". Then when the Task is resumed, all further execution occurs under the main UI thread.
Can someone explain exactly what is happening here and what I can do to make sure that my original thread is kept alive while my Task is paused?
Here is an example of my code:
//based on http://haukcode.wordpress.com/2013/01/29/high-precision-timer-in-netc/
public class HighPrecisionTimer : IDisposable
{
Task _task;
Task<Task> _taskWrapper;
CancellationTokenSource _cancelSource;
PauseTokenSource _pauseSource; //see http://blogs.msdn.com/b/pfxteam/archive/2013/01/13/cooperatively-pausing-async-methods.aspx
public bool IsPaused
{
get { return _pauseSource != null && _pauseSource.IsPaused; }
private set
{
if (value)
{
_pauseSource = new PauseTokenSource();
}
else
{
_pauseSource.IsPaused = false;
}
}
}
public bool IsRunning
{
get
{
return !IsPaused && _taskWrapper != null && _taskWrapper.Status == TaskStatus.Running;
}
}
public void Start()
{
if (IsPaused)
{
IsPaused = false;
}
else if (!IsRunning)
{
_cancelSource = new CancellationTokenSource();
_taskWrapper = Task.Factory.StartNew(
function: new Func<Task>(ExecuteAsync),
cancellationToken: _cancelSource.Token,
creationOptions: TaskCreationOptions.LongRunning,
scheduler: TaskScheduler.Default);
_task = _taskWrapper.Unwrap();
}
}
public void Stop()
{
if (_cancelSource != null)
{
_cancelSource.Cancel();
}
}
public void Pause()
{
IsPaused = !IsPaused;
}
async Task ExecuteAsync()
{
while (!_cancelSource.IsCancellationRequested)
{
if (_pauseSource != null && _pauseSource.IsPaused)
{
//this is the line that causes the current thread to "finish"...
await _pauseSource.Token.WaitWhilePausedAsync();
}
// DO CUSTOM STUFF...
}
_cancelSource = null;
_pauseSource = null;
}
public void Dispose()
{
if (IsRunning)
{
_cancelSource.Cancel();
}
}
}