扩展C#async/await不';不要等待
扩展: 如果按顺序执行的方法也存储在列表中,如何将ExecuteParallelAsync添加到该列表中扩展C#async/await不';不要等待,c#,async-await,C#,Async Await,扩展: 如果按顺序执行的方法也存储在列表中,如何将ExecuteParallelAsync添加到该列表中 private async Task ExecuteSequential() { List<Action> sequentialMethods = new List<Action>() { SomeMethod1, SomeMethod2, await ExecuteParallelAsync, // ?
private async Task ExecuteSequential()
{
List<Action> sequentialMethods = new List<Action>()
{
SomeMethod1,
SomeMethod2,
await ExecuteParallelAsync, // ???
SomeMethod3,
SomeMethod4
};
for ( int i = 0 ; i < sequentialMethods.Count ; i++ )
{
sequentialMethods.ElementAt( i ).Invoke();
}
}
当我删除每一个异步和每一个任务时,所有的任务都将按顺序运行,这一行是关键:
Parallel.ForEach( methods , ( currentMethod ) => currentMethod.Invoke() );
当我使用最后一句话时,一切正常
感谢所有人,您的所有想法、想法和努力都得到了帮助并受到了赞赏。您可以创建一个
操作,当调用该操作时,它将启动任务并等待任务完成,如下所示:
List<Action> sequentialMethods = new List<Action>()
{
SomeMethod1,
SomeMethod2,
() => ExecuteParallelAsync().Wait(),
SomeMethod3,
SomeMethod4
};
List sequentialMethods=新列表()
{
一些方法1,
一些方法2,
()=>ExecuteParallelAsync().Wait(),
一些方法3,
一些方法4
};
您可以创建一个操作,当调用该操作时,它将启动任务并等待任务完成,如下所示:
List<Action> sequentialMethods = new List<Action>()
{
SomeMethod1,
SomeMethod2,
() => ExecuteParallelAsync().Wait(),
SomeMethod3,
SomeMethod4
};
List sequentialMethods=新列表()
{
一些方法1,
一些方法2,
()=>ExecuteParallelAsync().Wait(),
一些方法3,
一些方法4
};
以下是一个版本:
private async Task ExecuteSequential()
{
var sequentialMethods = new List<Func<Task>>()
{
() => Task.Run(SomeMethod1),
() => Task.Run(() => SomeMethod2("Hey!")),
ExecuteParallelAsync,
() => Task.Run(SomeMethod3),
() => Task.Run(SomeMethod4)
};
for ( int i = 0 ; i < sequentialMethods.Count ; i++ )
{
Task t = sequentialMethods[i].Invoke();
await t;
// or just await sequentialMethods[i]();
}
}
编辑:测试
代码
My1
、My2
和My3
将在执行之间更改顺序,但始终在|124;|Start
和|End
以下是一个版本:
private async Task ExecuteSequential()
{
var sequentialMethods = new List<Func<Task>>()
{
() => Task.Run(SomeMethod1),
() => Task.Run(() => SomeMethod2("Hey!")),
ExecuteParallelAsync,
() => Task.Run(SomeMethod3),
() => Task.Run(SomeMethod4)
};
for ( int i = 0 ; i < sequentialMethods.Count ; i++ )
{
Task t = sequentialMethods[i].Invoke();
await t;
// or just await sequentialMethods[i]();
}
}
编辑:测试
代码
My1
、My2
和My3
将在执行之间更改顺序,但始终在|开始
和|结束
范围内
我再次面临最初的问题,即在ExecuteParallelAsync完成之前执行SomeMethod3
那么这不是异步编程的用例。您的要求是这是同步的
尤其如此,因为您说过MyMethod1
/MyMethod2
/MyMethod3
不是异步方法。如果是的话,那将是一场灾难。但是因为它们不是,所以我看不出在这里尝试使用async
和wait
有什么价值
但不要混淆异步和并行。您似乎希望在ExecuteParallelAsync
中调用的方法并行运行,这很好。您不需要async
和wait
例如:
private void ExecuteSequential()
{
列表顺序方法=新列表()
{
一些方法1,
一些方法2,
执行并行,
一些方法3,
一些方法4
};
for(int i=0;icurrentMethod.Invoke());
}
我再次面临最初的问题,即在ExecuteParallelAsync完成之前执行SomeMethod3
那么这不是异步编程的用例。您的要求是这是同步的
尤其如此,因为您说过MyMethod1
/MyMethod2
/MyMethod3
不是异步方法。如果是的话,那将是一场灾难。但是因为它们不是,所以我看不出在这里尝试使用async
和wait
有什么价值
但不要混淆异步和并行。您似乎希望在ExecuteParallelAsync
中调用的方法并行运行,这很好。您不需要async
和wait
例如:
private void ExecuteSequential()
{
列表顺序方法=新列表()
{
一些方法1,
一些方法2,
执行并行,
一些方法3,
一些方法4
};
for(int i=0;icurrentMethod.Invoke());
}
Await是一种语法糖,用于将方法切割成状态机。它将如何以多种方法切割列表?等待应该在调用方法时完成,不能动态生成。这是在编译时完成的。根据我的经验,ParallelFor
不能很好地使用异步函数。这还取决于MyMethod1
/MyMethod2
/MyMethod3
是如何实现的。它们是async
方法吗?不,它们不是。它们在基类中是受纯保护的虚拟void,因此在派生类中是受保护的重写void。我唯一更改的两个方法是ExecuteSequential和ExecuteParallelAsync from(async)void to async Task。如果它们不是异步的,您不能等待它们。您可以创建一个任务来等待它,然后创建其他任务来运行非异步代码。为什么?这只会降低代码的效率,没有任何好处。只需使用一个parallel for(这基本上就是wait is语法糖)将该方法切割成一个状态机。它将如何以多种方法切割列表?等待应该在调用方法时完成,不能动态生成。这是在编译时完成的。根据我的经验,ParallelFor
不能很好地使用异步函数。这还取决于MyMethod1
/MyMethod2
/MyMethod3
是如何实现的。它们是async
方法吗?不,它们不是。它们在基类中是受纯保护的虚拟void,因此在派生类中是受保护的重写void。我唯一更改的两个方法是ExecuteSequential和ExecuteParallelAsync from(async)void to async Task。如果它们不是异步的,您不能等待它们。您可以创建一个任务来等待它,然后创建其他任务来运行非异步代码。为什么?这只会降低代码的效率,没有任何好处。用一个平行的
private async Task ExecuteSequential()
{
SomeMethod1();
SomeMethod2();
await ExecuteParallelAsync();
SomeMethod3();
SomeMethod4();
};
class Program
{
public void MyMethod1() => Console.WriteLine("||My1");
public void MyMethod2() => Console.WriteLine("||My2");
public void MyMethod3() => Console.WriteLine("||My3");
private async Task ExecuteParallelAsync()
{
Console.WriteLine("||Start");
List<Action> methods = new List<Action>() { MyMethod1, MyMethod2, MyMethod3 };
await Task.Run(() => { Parallel.ForEach(methods,
(currentMethod) => currentMethod.Invoke()); }); // This could be just 'currentMethod();' (no Invoke())
Console.WriteLine("||End");
}
public void SomeMethod1() => Console.WriteLine("Some1");
public void SomeMethod2(string s) => Console.WriteLine($"Some2: {s}");
public void SomeMethod3() => Console.WriteLine("Some3");
public void SomeMethod4() => Console.WriteLine("Some4");
private async Task ExecuteSequential()
{
var sequentialMethods = new List<Func<Task>>()
{
() => Task.Run(SomeMethod1),
() => Task.Run(() => SomeMethod2("Hey!")),
ExecuteParallelAsync,
() => Task.Run(SomeMethod3),
() => Task.Run(SomeMethod4)
};
for (int i = 0; i < sequentialMethods.Count; i++)
{
await sequentialMethods[i]();
}
}
static async Task Main(string[] args)
{
await new Program().ExecuteSequential();
Console.WriteLine("All done");
}
}
Some1
Some2: Hey!
||Start
||My3
||My2
||My1
||End
Some3
Some4
All done