在C#6中,我有以下扩展名:
public static void With<T>(this T value, Action<T> action) {
action(value);
}
public static R With<T, R>(this T value, Func<T, R> function) {
return function(value);
}
有没有办法让这些扩展的Async版本?
更新
我正在添加一个例子来澄清。考虑(上下文是EF上下文):
IList<Post> posts = context.Posts.With(x => x.ToList());
现在,如果我想使用ToListAsync?
,该如何做到这一点IList<Post> posts = await context.Posts.WithAsync(x => x.ToListAsync());
或
IList<Post> posts = context.Posts.WithAsync(x => await x.ToListAsync());
什么是最好的方法,扩展如何?
答案 0 :(得分:2)
我强烈建议您不要在扩展方法中使用async
/ await
来跳过状态机的生成。只需返回任务并等待,或者在需要时等待await
您也可以将第二种方法用于异步案例
public static R With<T>(this T value, Func<T, R> function)
{
return function(value);
}
或者你可以只限制异步使用的方法
public static R WithAsync<T, R>(this T value, Func<T, R> function)
where R : Task
{
return function(value);
}
答案 1 :(得分:2)
我在asynchronous delegate types上发了一篇博文。总而言之,async
Action<T>
版Func<T, Task>
为async
,而Func<T, R>
版Func<T, Task<R>>
为public static void With<T>(this T value, Action<T> action) {
action(value);
}
public static R With<T, R>(this T value, Func<T, R> function) {
return function(value);
}
public static Task With<T>(this T value, Func<T, Task> function) {
return function(value);
}
public static Task<R> With<T, R>(this T value, Func<T, Task<R>> function) {
return function(value);
}
。
我建议您提供所有重载以实现最大可用性:
\s
答案 2 :(得分:0)
就像其他任何功能一样:
public static async Task With<T>(this T value, Func<T, Task> action) {
await action(value);
}
public static async Task<R> With<T, R>(this T value, Func<T, Task<R>> function) {
return await function(value);
}
答案 3 :(得分:0)
async
。Task
。如果您需要实际的退货类型,请使用Task<InsertReturnTypeHere>
代替Task
WithAsync
。这将允许With<T>
与异步实现共存,这也是常见的惯例。public static async Task WithAsync<T>(this T value, Action<T> action)
{
await actionAsync(value);
}
答案 4 :(得分:0)
public static void With<T>(this T value, Action<T> action) {
action(value);
}
让您的行动计划任务本身。 With
并不期望得到任何回报,因此它不必关心行动的运作方式。
public static R With<T, R>(this T value, Func<T, R> function) {
return function(value);
}
提供返回任务的function
。您可以像var y = await x.With(async z => { /* ... */ });
一样使用它。
结论:您无需进行任何更改。
答案 5 :(得分:0)
这取决于您打算处理的处理量以及您打算如何处理它。
你需要一个线程吗?如果是这样,那么使用Task提供了一个很好的替代线程。
否则,线程池中可能已经有很多线程可供您使用,See this question您可以使用'BeginInvoke'访问这些线程。
static void _TestLogicForBeginInvoke(int i)
{
System.Threading.Thread.Sleep(10);
System.Console.WriteLine("Tested");
}
static void _Callback(IAsyncResult iar)
{
System.Threading.Thread.Sleep(10);
System.Console.WriteLine("Callback " + iar.CompletedSynchronously);
}
static void TestBeginInvoke()
{
//Callback is written after Tested and NotDone.
var call = new System.Action<int>(_TestLogicForBeginInvoke);
//Start the call
var callInvocation = call.BeginInvoke(0, _Callback, null);
//Write output
System.Console.WriteLine("Output");
int times = 0;
//Wait for the call to be completed a few times
while (false == callInvocation.IsCompleted && ++times < 10)
{
System.Console.WriteLine("NotDone");
}
//Probably still not completed.
System.Console.WriteLine("IsCompleted " + callInvocation.IsCompleted);
//Can only be called once, should be called to free the thread assigned to calling the logic assoicated with BeginInvoke and the callback.
call.EndInvoke(callInvocation);
}//Callback
输出应为:
Output
NotDone
NotDone
NotDone
NotDone
NotDone
NotDone
NotDone
NotDone
NotDone
IsCompleted False
Tested
Callback False
您定义的任何“委托”类型都可以使用委托实例的“BeginInvoke”方法在线程池上调用。另请参阅MSDN