in SimpleDUTClientLibrary/RpcClient.cs [731:798]
private async Task<string> _RunJob(string command, string args = null,
int pollingInterval = 60,
int timeout = 0,
int pollingDelay = 60,
CancellationToken? cancellationToken = null,
bool returnExObject = false)
{
Timer pollingTimer = null;
Timer timeoutTimer = null;
TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
Action<int> completionCallback = (x) => taskCompletionSource.TrySetResult(true);
var jobid = StartJobWithNotification(command, args, completionCallback);
if (pollingInterval > 0)
{
// we need to setup polling
TimerCallback pollingAction = (o) =>
{
try
{
if (CheckJobCompletion(jobid))
{
pollingTimer.Change(Timeout.Infinite, Timeout.Infinite);
taskCompletionSource.TrySetResult(true);
}
}
catch (Exception e)
{
taskCompletionSource.TrySetException(e);
}
};
pollingTimer = new Timer(pollingAction, null, pollingInterval * 1000, pollingDelay * 1000);
}
if (timeout > 0)
{
timeoutTimer = new Timer((o) => { taskCompletionSource.SetException(new TimeoutException("RunWithResult timed out.")); }, null, timeout * 1000, Timeout.Infinite);
}
var tsk = taskCompletionSource.Task;
var token = cancellationToken ?? CancellationToken.None;
token.Register(() => taskCompletionSource.TrySetCanceled());
try
{
// prevents deadlock if someone calls RunJob on a UI thread.
await tsk.ConfigureAwait(continueOnCapturedContext: false);
}
catch (OperationCanceledException e)
{
StopJob(jobid);
// don't throw until we clean up the timers.
}
pollingTimer?.Dispose();
timeoutTimer?.Dispose();
// if we were canceled, throw cancelation exception here
token.ThrowIfCancellationRequested();
if (taskCompletionSource.Task.IsFaulted)
{
throw taskCompletionSource.Task.Exception;
}
return (returnExObject) ? GetJobResultEx(jobid) : GetJobResult(jobid);
}