Reputation: 2899
I have an Azure Worker Role that calls 4 different services, I want to be able to run each in it's own thread and when one completes, kick off another iteration of it. Since they all take different times to run, I do not want to await for all of them before I kick off another occurrence when one completes. I have this which calls them all in sequence
public class WorkerRole : RoleEntryPoint
{
private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
private readonly ManualResetEvent runCompleteEvent = new ManualResetEvent(false);
public override void Run()
{
Trace.TraceInformation("Polling.Worker is running");
try
{
this.RunAsync(this.cancellationTokenSource.Token).Wait();
}
finally
{
this.runCompleteEvent.Set();
}
}
public override bool OnStart()
{
// Set the maximum number of concurrent connections
ServicePointManager.DefaultConnectionLimit = 12;
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
bool result = base.OnStart();
Trace.TraceInformation("Polling.Worker has been started");
return result;
}
public override void OnStop()
{
Trace.TraceInformation("Polling.Worker is stopping");
this.cancellationTokenSource.Cancel();
this.runCompleteEvent.WaitOne();
base.OnStop();
Trace.TraceInformation("Polling.Worker has stopped");
}
private async Task RunAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
await Task.Run(() =>
{
Debug.WriteLine("Starting Reddit Service");
RedditService.GetObjects();
Debug.WriteLine("Completed Reddit Service");
});
await Task.Run(() =>
{
Debug.WriteLine("Starting TV Show Service");
TVShowTicketService.GetObjects();
Debug.WriteLine("Completed TV Show Service");
});
await Task.Run(() =>
{
Debug.WriteLine("Starting Play By Play Service");
PlayByPlayService.GetObjects();
Debug.WriteLine("Completed Play By Play Service");
});
await Task.Run(() =>
{
Debug.WriteLine("Starting Profile Service");
ProfileService.Main();
Debug.WriteLine("Completed Profile Service");
});
await Task.Delay(1000);
}
}
}
I know that I am awaiting each thread, and I want to be able basically have some while mechanism that just repeats each function once it is complete, without worrying about the other threads.
Upvotes: 1
Views: 2922
Reputation: 70671
If I've understood correctly, all you need to do is move your while
loop into each task:
private async Task RunAsync(CancellationToken cancellationToken)
{
await Task.WhenAll(
Task.Run(() =>
{
while (!cancellationToken.IsCancellationRequested)
{
Debug.WriteLine("Starting Reddit Service");
RedditService.GetObjects();
Debug.WriteLine("Completed Reddit Service");
await Task.Delay(1000);
}
}),
Task.Run(() =>
{
while (!cancellationToken.IsCancellationRequested)
{
Debug.WriteLine("Starting TV Show Service");
TVShowTicketService.GetObjects();
Debug.WriteLine("Completed TV Show Service");
await Task.Delay(1000);
}
}),
Task.Run(() =>
{
while (!cancellationToken.IsCancellationRequested)
{
Debug.WriteLine("Starting Play By Play Service");
PlayByPlayService.GetObjects();
Debug.WriteLine("Completed Play By Play Service");
await Task.Delay(1000);
}
}),
Task.Run(() =>
{
while (!cancellationToken.IsCancellationRequested)
{
Debug.WriteLine("Starting Profile Service");
ProfileService.Main();
Debug.WriteLine("Completed Profile Service");
await Task.Delay(1000);
}
}));
}
You can improve readability and maintainability by encapsulating the repeated elements in a helper method:
private async Task RunAsync(CancellationToken cancellationToken)
{
await Task.WhenAll(
RunServiceAsync(cancellationToken, RedditService.GetObjects, "Reddit"),
RunServiceAsync(cancellationToken, TVShowTicketService.GetObjects, "TV Show"),
RunServiceAsync(cancellationToken, PlayByPlayService.GetObjects, "Play By Play"),
RunServiceAsync(cancellationToken, ProfileService.Main, "Profile"));
}
Task RunServiceAsync(CancellationToken cancellationToken, Action service, string description)
{
return Task.Run(() =>
{
while (!cancellationToken.IsCancellationRequested)
{
Debug.WriteLine("Starting " + description + " Service");
service();
Debug.WriteLine("Completed " + description + " Service");
await Task.Delay(1000);
}
});
}
Upvotes: 1