I have a class used as a parent to all my ViewModel
s. It contains a specific method used to call others methods, and show loading messages and message boxes on error (mainly):
public class BaseViewModel
{
async public void Try(Func<Task> action, string errorMessage = null, string waitMessage = null)
{
try
{
if (waitMessage != null)
ShowLoading(waitMessage);
await action();
}
catch (Exception e)
{
ShowError(errorMessage, e);
}
finally
{
HideLoading();
}
}
}
It is asynchronous, so my ShowLoading
can be animated and stuff like that.
- Is it correctly implemented?
It will always get anonymous (lambda) parameterless Task
s. My main issue is on how to actually construct these Task
s. Let's say I have a Command
in a ViewModelBase
's child, which call the following method when executed:
private void OnMyCommandExecute()
{
Try(() =>
{
Thread.Sleep(5000);
}, "error", "please wait");
}
It does not compile because Not all code paths return a value in lambda expression of type 'System.Func<System.Threading.Tasks.Task>'
. Obvious, since we await
this Func
. Which leads me to the second question:
- What should I put inside my
Try
call in this example for it to work?
I tried some really ugly things, and I really hope the answer is way different, else it will be a pain of readability:
Try(async () =>
{
return await Task.Factory.StartNew(() =>
{
SharePointService.Connect(Connection);
IsConnected = true;
});
}
It does not compile, but at this point, it's better like that. Error on return
: Since 'System.Func<System.Threading.Tasks.Task>' is an
asyncmethod that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task<T>'?