I have written the following method:
async Task<T> Load<T>(Func<T> function)
{
T result = await Task.Factory.StartNew(() =>
{
IsLoading = true;
T functionResult = function.Invoke();
IsLoading = false;
return functionResult;
});
return result;
}
I have two questions:
Can I simplify the code?
I can pass any parameterless method/function to this method to get a return type of any type. E.g.:
string GetString()
By saying:
string someString = await Load(GetString);
Is there a way I could make this method more generic so that I could pass methods with parameters as well? E.g. One single method that would also accept:
string GetString(string someString)
string GetString(string someString, int someInt)
This might look like:
string someString = await Load(GetString("string"));
string someString = await Load(GetString("string", 1));
This obviously doesn't work, but as the Load<T>
method doesn't reference the parameters, I feel
this should be possible somehow.
Can I simplify the code?
You can both simplify it, and make it more correct. There are a few problems with the code as-written:
IsLoading
is a UI-bound property, so it should be updated on the UI thread, not a background thread. Some frameworks like WPF on Windows allow you to bend the rules, but other XAML-based frameworks do not.IsLoading
to false
if the loading fails.Task.Factory.StartNew
should be avoided; it's a dangerous, low-level method. Use Task.Run
if you need to run a method on a background thread.async Task<T> Load<T>(Func<T> function)
{
IsLoading = true;
try
{
return await Task.Run(function);
}
finally
{
IsLoading = false;
}
}
Is there a way I could make this method more generic so that I could pass methods with parameters as well?
You can use lambdas for this:
string someString = await Load(() => GetString("string"));
string someString = await Load(() => GetString("string", 1));