[英]Async Method Using Generic Func<T>
我寫了以下方法:
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;
}
我有兩個問題:
我可以簡化代碼嗎?
我可以將任何無參數方法/函數傳遞給此方法以獲得任何類型的返回類型。 例如:
string GetString()
通過說:
string someString = await Load(GetString);
有沒有辦法讓這個方法更通用,以便我也可以傳遞帶參數的方法? 例如,一種也可以接受的單一方法:
string GetString(string someString) string GetString(string someString, int someInt)
這可能看起來像:
string someString = await Load(GetString("string")); string someString = await Load(GetString("string", 1));
這顯然是行不通的,但是由於Load<T>
方法沒有引用參數,我覺得這應該是可能的。
我可以簡化代碼嗎?
您既可以簡化它,也可以使它更正確。 編寫的代碼存在一些問題:
IsLoading
是一個 UI 綁定屬性,因此它應該在 UI 線程上更新,而不是在后台線程上。 某些框架(例如 Windows 上的 WPF)允許您改變規則,但其他基於 XAML 的框架則不允許。IsLoading
設置為false
。Task.Factory.StartNew
; 這是一種危險的低級方法。 如果您需要在后台線程上運行方法,請使用Task.Run
。async Task<T> Load<T>(Func<T> function)
{
IsLoading = true;
try
{
return await Task.Run(function);
}
finally
{
IsLoading = false;
}
}
有沒有辦法讓這個方法更通用,以便我也可以傳遞帶參數的方法?
您可以為此使用 lambda:
string someString = await Load(() => GetString("string"));
string someString = await Load(() => GetString("string", 1));
有沒有辦法讓這個方法更通用,以便我也可以傳遞帶參數的方法?
async Task<R> Load<T, R>(Func<T, R> function, T parameter)
{
R result = await Task.Run(() =>
{
return function.Invoke(parameter);
});
return result;
}
您可以將 function 需要的任何參數捆綁到T
中。
如果您仍然需要單個參數,則必須創建額外的重載。
您也可以嘗試params
傳遞任意數量的參數,但它們必須都是相同類型,除非您以某種形式使用運行時多態性。
Task<T> Load<T>(Func<T> function)
{
return Task.Factory.StartNew(() =>
{
IsLoading = true;
var functionResult = function.Invoke();
IsLoading = false;
return functionResult;
});
}
async 和 await 是可選的,因為您可以返回任務。 在 finally 中使用 try... finally 阻止和更新 IsLoading = false 可能是有意義的
有沒有辦法讓這個方法更通用
一種選擇是像這樣嵌套它:
public bool IsLoading { get; set; }
public Task<string> GetString(string input) => Task.FromResult($"ret for input {input}");
public async Task<TReturn> Load<TReturn>(Func<Task<TReturn>> cb)
{
IsLoading = true;
var ret = await cb();
IsLoading = false;
return ret;
}
public async Task Demo()
{
var ret = await Load(() => GetString("input"));
}
(我也讓 GetString() 方法返回了一個任務。假設如果這對你的情況沒有意義,那么它很容易調整。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.