我有3个任务:
private async Task<Cat> FeedCat() {}
private async Task<House> SellHouse() {}
private async Task<Tesla> BuyCar() {}
Run Code Online (Sandbox Code Playgroud)
他们都需要在我的代码可以继续之前运行,我也需要每个代码的结果.结果没有任何共同之处
如何调用并等待3个任务完成然后获得结果?
我尝试阅读 stackoverflow 中有关 的实际使用的许多文章和问题async/await
,因此基本上是异步方法调用,但不知何故我仍然无法解码它如何提供并行性和非阻塞行为。我参考了一些这样的帖子
https://news.ycombinator.com/item?id=19010989
所以如果我写一段这样的代码
var user = await GetUserFromDBAsync();
var destination = await GetDestinationFromDBAsync();
var address = await GetAddressFromDBAsync();
Run Code Online (Sandbox Code Playgroud)
尽管这三个方法都是异步的,但代码仍然不会转到第二行从数据库获取,直到完全从数据库destination
获取。user
那么这里的并行性和非阻塞行为在哪里呢asyn/await
?在执行下一行之前,它仍然等待完成第一个操作。
或者我对异步的总体理解是错误的?
编辑
任何例子都会很有帮助!
我有一系列任务,每个任务取决于前一个任务的输出.我想将它表示为单个Task
对象,其结果是序列末尾的输出.(如果任务不依赖于彼此,那么我可以并行执行,我会使用TaskFactory.ContinueWhenAll
.)
我希望能够实现这个方法:
static Task<TState> AggregateAsync<T, TState>(
IEnumerable<T> items,
TState initial,
Func<TState, T, Task<TState>> makeTask);
Run Code Online (Sandbox Code Playgroud)
我怎样才能有效地依次运行任务呢?我正在使用C#4.0,所以我无法使用async
/ await
为我做这件事.
编辑:我可以AggregateAsync
像这样写:
static Task<TState> AggregateAsync<T, TState>(IEnumerable<T> items, TState initial, Func<TState, T, Task<TState>> makeTask)
{
var initialTask = Task.Factory.StartNew(() => initial);
return items.Aggregate(
initialTask,
(prevTask, item) =>
{
prevTask.Wait(); // synchronous blocking here?
return makeTask(prevTask.Result, item);
});
}
Run Code Online (Sandbox Code Playgroud)
但是我肯定会得到一批任务,每个任务同步等待前面的那个任务?
以一个简单的酒店实体为例:
class Hotel
{
public int NumberOfRooms { get; set; }
public int StarRating { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
请考虑C#5.0中的以下代码:
public void Run()
{
var hotel = new Hotel();
var tasks = new List<Task> { SetRooms(hotel), SetStars(hotel) };
Task.WaitAll(tasks.ToArray());
Debug.Assert(hotel.NumberOfRooms.Equals(200));
Debug.Assert(hotel.StarRating.Equals(5));
}
public async Task SetRooms(Hotel hotel)
{
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
hotel.NumberOfRooms = 200;
}
public async Task SetStars(Hotel hotel)
{
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
hotel.StarRating = 5;
}
Run Code Online (Sandbox Code Playgroud)
两次对Debug.Assert()的调用都成功通过.我不明白在两个任务完成后,Hotel的实例包含两个并行运行的方法的赋值.
我认为,当await
被调用(在这两个SetRooms()
和SetStars()
),"快照"酒店实例的创建(同时具有NumberOfRooms
与StarRating
设置为0).所以我的期望是两个任务之间会有一个竞争条件,最后一个任务将被复制回hotel
两个属性中的一个产生0. …
我正在寻找一种方法来异步执行go中的两个函数,它返回不同的结果和错误,等待它们完成并打印两个结果.另外,如果函数返回错误之一,我不想等待另一个函数,只打印错误.例如,我有这个功能:
func methodInt(error bool) (int, error) {
<-time.NewTimer(time.Millisecond * 100).C
if error {
return 0, errors.New("Some error")
} else {
return 1, nil
}
}
func methodString(error bool) (string, error) {
<-time.NewTimer(time.Millisecond * 120).C
if error {
return "", errors.New("Some error")
} else {
return "Some result", nil
}
}
Run Code Online (Sandbox Code Playgroud)
这里https://play.golang.org/p/-8StYapmlg就是我实现它的方式,但我认为它有太多的代码.它可以通过使用接口{}来简化,但我不想这样做.我想要更简单的东西,例如,可以使用async/await在C#中实现.可能有一些库可以简化这种操作.
更新:感谢您的回复!我得到多快帮助真是太棒了!我喜欢WaitGroup的用法.它显然使代码对更改更加健壮,因此我可以轻松地添加另一个异步方法,而不会最终改变方法的确切数量.但是,与C#相比,仍有如此多的代码.我知道在go中我不需要明确地将方法标记为异步,使它们实际上返回任务,但是方法调用看起来要简单得多,例如,考虑这个链接实际上也需要捕获异常 顺便说一下,我找到了在我的任务中,我实际上不需要知道我想要运行异步的函数的返回类型,因为无论如何它将被整理到json,现在我只是在go-kit的端点层调用多个服务.
每当我尝试调试代码但无法继续时,我都会收到错误。
未找到 AsyncMethodBuilder.cs
背景信息:
我必须用最少的时间压缩大量的文档。我有一个压缩库,我能够同步进行压缩。但为了加快速度,我想并行压缩文档(一次压缩的文档没有可编程的),这样 1.我会正确利用 CPU 并在最佳时间内完成工作。
为了实现上述目标,我按照此链接创建了多个任务并等待它们完成
下面是我尝试过的代码。
public static class CompressAllTechniques
{
public static void Main()
{
GoCallAPIAsync();
}
private static async void GoCallAPIAsync()
{
try
{
List<Task> TaskList = new List<Task>();
// For Sample testing I have taken 4 files and will iterate through them to check the timings
const string originalFile1 = @"Sample Data\source";
const string originalFile2 = @"Sample Data\source1";
const string originalFile3 = @"Sample Data\Original";
const string originalFile4 = @"Sample Data\Original1";
List<string> …
Run Code Online (Sandbox Code Playgroud) 我有一个看起来很简单的问题,但我似乎无法在任何地方找到答案。
鉴于我有多个不同类型的任务数组,例如
Task<Dog>[] dogTasks = GetDogTasks();
Task<Cat>[] catTasks = GetCatTasks();
Task<Fish>[] fishTasks = GetFishTasks();
Run Code Online (Sandbox Code Playgroud)
完成这些任务的最佳方法是什么WaitAll()
?
我认为这里的async/await关键字是多余的.
Parallel.Invoke(
async () => await DoSomethingAsync(1).ConfigureAwait(false),
async () => await DoSomethingAsync(2).ConfigureAwait(false)
);
Run Code Online (Sandbox Code Playgroud)
给定了许多任务返回方法,有没有更直接的方法来并行运行它们并在完成所有操作后返回?
我有2个简单的方法,我希望进程在完成之前不会继续.因此,我使用await Task.WaitAll(tasks); 但编译器在这一行给我错误:
Severity Code Description Project File Line Suppression State
Error CS1503 Argument 1: cannot convert from '
'System.Collections.Generic.List<System.Threading.Tasks.Task>' to
'System.Threading.Tasks.Task'
Run Code Online (Sandbox Code Playgroud)
我为什么要自己手动转换?我以为这会由编译器来完成......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
internal class Program
{
public static void Count1()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Count 1 " + i);
Thread.Sleep(100);
}
}
public static void Count2()
{
for (int i = 0; i < 20; i++)
{
Console.WriteLine("Count 2 " …
Run Code Online (Sandbox Code Playgroud) 我有多个REST API调用,我想以并行方式进行.例如
我有一个REST API调用CreateData().我想在服务器中创建1000个数据,适用于4-5个并行线程中的多线程操作.
我是C++开发人员,知道多线程如何在C++中工作.我在C#编码方面很天真.我知道异步任务,但不知道如何实现上述任务.
var response = await Task.Run(()=>CreateData());
Run Code Online (Sandbox Code Playgroud)
现在我依次按顺序进行,一旦我收到了之前CreateData()的响应,我就会在一个线程中创建数据.它正在严重影响性能并花费大量时间.
我想创建5个线程,它们将以并行方式为所有1000个用户执行REST API调用.
我有两个长时间运行的任务想要执行,然后继续执行。我遇到的问题是,在两个长时间运行的任务发出信号之前,延续正在运行。这两个任务没有错误,当延续开始时它们才刚刚开始。目的是前两个任务可以并行运行,但后续任务只能在它们都完成后运行。
我可能忽略了一些非常简单的事情,但据我所知,我正在遵循问题中建议的模式运行多个异步任务并等待它们全部完成。我意识到我可能可以省去,.ContinueWith()
因为后面的代码Task.WhenAll()
将隐式地成为延续,但我更喜欢保留显式的延续(除非它是我的问题的原因)。
private async Task MyMethod()
{
var tasks = new List<Task>
{
new Task(async () => await DoLongRunningTask1()),
new Task(async () => await DoLongRunningTask2())
};
Parallel.ForEach(tasks, async task => task.Start());
await Task.WhenAll(tasks)
.ContinueWith(async t =>{
//another long running bit of code with some parallel
//execution based on the results of the first two tasks
}
, TaskContinuationOptions.OnlyOnRanToCompletion);
}
private async Task DoLongRunningTask1()
{
... long running operation ...
}
private async Task DoLongRunningTask2() …
Run Code Online (Sandbox Code Playgroud) 我需要使用3个任务创建一个foreach循环,这需要等到所有3个任务完成后再移动到下一个任务.就像是
foreach (class r in sets)
{
Task.Factory.StartNew(() => {
DoThisFunction1();
}, TaskCreationOptions.LongRunning);
Task.Factory.StartNew(() => {
DoThisFunction2();
}, TaskCreationOptions.LongRunning);
Task.Factory.StartNew(() => {
DoThisFunction3();
}, TaskCreationOptions.LongRunning);
}
Run Code Online (Sandbox Code Playgroud)
有人可以给出一个简单的方法如何做到这一点?
c# ×11
async-await ×6
asynchronous ×6
.net ×4
task ×4
.net-4.5 ×1
c#-4.0 ×1
c#-5.0 ×1
channel ×1
foreach ×1
go ×1
goroutine ×1
loops ×1
threadpool ×1