I have an existing system with several long running operations. I was hoping to find a simple way to wrap these operations in tasks and give the user a busy status notification.
This is using .net 3.5 and I am using the TPL back port. Unfortunately async/await cannot be used here.
I've tried to come up with solution in a simple test form shown below and have run into some problems wrapping my head around this.
The below method only displays the first 2-3 tasks, after that UI doesn't get updated until all are complete. Why is this?
private void RunTaskUpdateBefore (string msg)
{
UpdateUI (msg);
Task task = Task.Factory.StartNew (() =>
{
// simulate some work being done
Thread.Sleep (1000);
});
task.Wait ();
}
I was hoping this method would work, but doesn't update UI until all tasks are completed
private void ChildTaskExternalWait (string msg)
{
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext ();
Task task = Task.Factory.StartNew (() =>
{
Task.Factory.StartNew (() =>
{
UpdateUI (msg);
}, System.Threading.CancellationToken.None, TaskCreationOptions.None, uiScheduler);
// simulate some work being done
Thread.Sleep (1000);
});
task.Wait (); // I assume this is the problem
}
The below method works great but I'm not sure if I can use it in my project. It is a fairly large complicated system, the operations happen in many different classes and are controlled by a legacy system that we can't modify. I'd assume I'd have to try to create some sort of global tasking queue to do this?
private Task RunTaskInternalWaitOnPrevious (string msg, Task t1 = null)
{
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext ();
Task task = Task.Factory.StartNew (() =>
{
if (t1 != null)
{
t1.Wait ();
}
Task.Factory.StartNew (() =>
{
UpdateUI (msg);
}, System.Threading.CancellationToken.None, TaskCreationOptions.None, uiScheduler);
// simulate some work being done
Thread.Sleep (2000);
});
return task;
}
My test form implementation:
private void button1_Click (object sender, EventArgs e)
{
// Only displays the first 2-3 tasks. After that UI doesn't get updated until all are complete
RunTaskUpdateBefore ("Task 1");
RunTaskUpdateBefore ("Task 2");
RunTaskUpdateBefore ("Task 3");
RunTaskUpdateBefore ("Task 4");
RunTaskUpdateBefore ("Task 5");
RunTaskUpdateBefore ("Task 6");
RunTaskUpdateBefore ("Task 7");
// this works with any number of tasks
// Unfortunately I'm not sure if I can use it in my application (see above notes)
//var t1 = RunTaskInternalWaitOnPrevious ("Task 1");
//var t2 = RunTaskInternalWaitOnPrevious ("Task 2", t1);
// and so on
}
private void UpdateUI (string msg)
{
this.textBox1.Text += msg;
this.textBox1.Text += System.Environment.NewLine;
}
update/clarification
*My tasks can not run in parallel.
*I want to inform the user that work is being done at each step.
*No other UI input can happen while the tasks are running.
The tasks are not centralized to a particular piece of code and happen all over the place. I'm not sure how else to describe my situation, sorry.