I'm currently working in a Windows.Forms
project where its very common that I need to show a responsive feedback form while a task runs. These tasks take typically around 5 to 10 seconds to complete and the user can't do anything else until the task has successfully finished or failed.
To keep the UI responsive I've cooked up a little helper class. I'm pretty new to tasks and the async programming environment so I am not sure if I'm overkilling things here or going off in a completely wrong direction:
This is the small helper class:
internal sealed class TaskManagerWithFeedbackDialog<TController> where TController : IViewController, new()
{
public static Task<TReturn> RunTask<TReturn>(Func<TReturn> func)
{
if (func == null)
{
throw new ArgumentNullException("func");
}
var manager = new _AsyncTaskManager<TReturn>(func);
using (var view = new TController())
{
var task = manager.Start(view);
view.ShowViewDialog();
return task;
}
}
private class _AsyncTaskManager<T>
{
private readonly Func<T> taskFunc;
public _AsyncTaskManager(Func<T> func)
{
taskFunc = func;
}
public Task<T> Start(IViewController feedBackView)
{
var task = Task.Factory.StartNew(taskFunc);
task.ContinueWith(t =>
{
feedBackView.CloseView();
}, TaskContinuationOptions.OnlyOnFaulted);
task.ContinueWith(t =>
{
feedBackView.CloseView();
return t.Result;
}, TaskContinuationOptions.NotOnFaulted);
return task;
}
}
}
Where the implementation of IViewController.CloseView()
would look like this:
public virtual void CloseView()
{
if (View.InvokeRequired)
{
View.Invoke(new Action(View.Close));
}
else
{
View.Close();
}
}
Another issue I am not sure about is where is the best place to handle ArregateException
?. Right now I don't handle anything as I don't need to clean up anything if a task fails. I simply check the returned task for any errors. Is this the right thing to do? Do async tasks always fail 'silently'? If I needed to clean up, where would it be? Inside .ContinueWith( .... , TaskContinuationOptions.OnlyOnFaulted)
?