以下代码的目标是将任何给定的函数强制转换为等待函数。我们的想法是在从数据库中获取数据时使用它,使代码可以灵活地使用同步获取函数(强制使用当前的ORM),或者使用与async完全相同的函数。
我知道代码背后的概念可能有很多问题。到目前为止,我只是想摆脱编译器错误,所以我可以运行代码并检查行为。但我当然愿意事先讨论这个概念,如果背后的整个想法是错误的,那么就更有效地利用我的时间寻找另一种解决方案。
async static void Main()
{
// The following line gives a compiler error:
// Error 1 The best overloaded method match for 'CastFuncToTask<int>(System.Func<int>)' has some invalid arguments
int task = await CastFuncToTask<int>(TestFunc(2));
}
private static Task<T> CastFuncToTask<T>(Func<T> func)
{
TaskCompletionSource<T> taskCompletionSource = new TaskCompletionSource<T>();
T result = func.Invoke();
taskCompletionSource.SetResult(result);
return taskCompletionSource.Task;
}
private static int TestFunc(int testInt)
{
return testInt * 2;
}
答案 0 :(得分:11)
运行.NET 4.5,您可以通过以下方式大大简化代码:
int task = await Task.FromResult(TestFunc(2));
无需将自己包裹在TaskCompletionSource
。
我知道这个概念可能有很多问题 代码背后。
如果您尝试做的是异步查询数据库,此解决方案肯定无济于事。它只会人为地将您的结果包装在Task
中。如果您确实想要异步查询数据库,则需要使用数据库提供程序提供的异步方法。
如果您正在使用MySQL并寻找支持异步的驱动程序,请查看Dapper
答案 1 :(得分:3)
将其更改为
int task = await CastFuncToTask<int>(()=>TestFunc(2));
在您的代码中,为CastFuncToTask
提供的输入为int
(TestFunc
返回的内容。)但需要委托Func<T>
。
答案 2 :(得分:2)
我的方法是:
public Task<int> SetOffAsync()
{
return Task<int>.Factory.StartNew(() =>
{
/*do something else*/
return 42;
});
}
你可以这样称呼:
int var = await SetOffAsync();
答案 3 :(得分:1)
使用Windows窗体应用程序,我确认第一个调用是阻止第二个isn&t。因此,最好的解决方案是将Task.Run()
与lambda表达式一起使用。
private async void button1_Click(object sender, EventArgs e)
{
button1.Text = "...";
var result = await Task.FromResult(TestFunc(2));
button1.Text = result.ToString();
}
private async void button2_Click(object sender, EventArgs e)
{
button2.Text = "...";
var result = await Task.Run(() => TestFunc(2));
button2.Text = result.ToString();
}
private int TestFunc(int x)
{
System.Threading.Thread.Sleep(5000);
return x;
}
编译器无法知道您不想评估TestFunc(2),而是将其用作委托,并且只是首先执行该方法,而Task.FromResult将只包含return value
任务。这不是你想要的。
答案 4 :(得分:0)
等待Task.Run(()=> obj.functionname());
答案 5 :(得分:0)
下面的代码可能会帮助其他人:
注意:GenericMethod是参数名称,我们将其作为泛型类型的输入(T1)和输出(T2)作为Func传递。 Task Factory将提供必要的访问权限以运行您的任务。
public async Task<T2> GenericAsyncCall<T1, T2>(Func<T1, T2> GenericMethod, T1 input)
{
var _output = await Task.Factory.StartNew(() => {
var output = GenericMethod.Invoke(input);
return output;
});
return (T2)_output;
}