troubleshooting Question

Need help with awaitable tasks

Avatar of Russ Suter
Russ Suter asked on
.NET ProgrammingC#
10 Comments1 Solution123 ViewsLast Modified:
I'm used to doing things the old-fashioned way with BackgroundWorker objects and multiple threads. I'm trying to figure out how to use the (seemingly better) awaitable task method of doing things. I created a UserControl with 3 progress bars. The UserControl code looks like this:
	public partial class MultiTaskThingy : UserControl
	{
		public MultiTaskThingy()
		{
			InitializeComponent();
		}

		public async Task<AsyncStatus> RunMultipleTasks(AsyncProgress<AsyncStatus> progress, CancellationToken cToken)
		{
			AsyncThingy thingy = new AsyncThingy();
			AsyncStatus overallStatus = new AsyncStatus();
			var localProgress = new AsyncProgress<AsyncStatus>(ReportProgress);
			List<Task<AsyncStatus>> taskList = new List<Task<AsyncStatus>>() { thingy.PseudoTask("1", localProgress, cToken), thingy.PseudoTask("2", localProgress, cToken), thingy.PseudoTask("3", localProgress, cToken) };
			try
			{
				await Task.WhenAll(taskList);
			}
			catch (Exception ex)
			{
				System.Diagnostics.Debug.Print(ex.Message);
			}
			return overallStatus;
		}

		void ReportProgress(AsyncStatus value)
		{
			switch (value.Context)
			{
				case "1":
					progressBar1.Invoke(pb => { pb.Value = value.PercentComplete; });
					break;
				case "2":
					progressBar2.Invoke(pb => { pb.Value = value.PercentComplete; });
					break;
				case "3":
					progressBar3.Invoke(pb => { pb.Value = value.PercentComplete; });
					break;
				default:
					throw new ArgumentOutOfRangeException($"Context {value.Context} is not valid");
			}
		}
	}
I then have that UserControl on a Windows Form with a single button that kicks things off. The button code is:
		private async void buttonDoManyThings_Click(object sender, EventArgs e)
		{
			_cts = new CancellationTokenSource();
			var progressIndicator = new AsyncProgress<AsyncStatus>(ReportProgress);
			await Task.Run(() => multiTaskThingy.RunMultipleTasks(progressIndicator, _cts.Token));
			_cts.Dispose();
			_cts = null;
		}
All 3 tasks run and the calling UI thread isn't blocked. However, the tasks run sequentially rather than concurrently. This isn't what I expected. Can anyone tell me what I'm doing wrong?

FYI, The AsyncThingy class contains the PseudoTask method which is nothing more than a loop counter with an arbitrary length between 5 and 15 seconds. It just reports a progress back to the caller.
Join the community to see this answer!
Join our exclusive community to see this answer & millions of others.
Unlock 1 Answer and 10 Comments.
Join the Community
Learn from the best

Network and collaborate with thousands of CTOs, CISOs, and IT Pros rooting for you and your success.

Andrew Hancock - VMware vExpert
See if this solution works for you by signing up for a 7 day free trial.
Unlock 1 Answer and 10 Comments.
Try for 7 days

”The time we save is the biggest benefit of E-E to our team. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange.

-Mike Kapnisakis, Warner Bros