在metro应用程序中,我需要执行许多WCF调用.有大量的调用,所以我需要在并行循环中进行调用.问题是并行循环在WCF调用完成之前退出.
你会如何重构这个按预期工作?
var ids = new List<string>() { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
var customers = new System.Collections.Concurrent.BlockingCollection<Customer>();
Parallel.ForEach(ids, async i =>
{
ICustomerRepo repo = new CustomerRepo();
var cust = await repo.GetCustomer(i);
customers.Add(cust);
});
foreach ( var customer in customers )
{
Console.WriteLine(customer.ID);
}
Console.ReadKey();
Run Code Online (Sandbox Code Playgroud) 我有一个我创建的任务列表,如下所示:
public async Task<IList<Foo>> GetFoosAndDoSomethingAsync()
{
var foos = await GetFoosAsync();
var tasks = foos.Select(async foo => await DoSomethingAsync(foo)).ToList();
...
}
Run Code Online (Sandbox Code Playgroud)
通过使用.ToList()
,任务都应该开始.现在我想等待完成并返回结果.
这适用于上面的...
块:
var list = new List<Foo>();
foreach (var task in tasks)
list.Add(await task);
return list;
Run Code Online (Sandbox Code Playgroud)
它做我想要的,但这似乎相当笨拙.我宁愿写一些更简单的东西:
return tasks.Select(async task => await task).ToList();
Run Code Online (Sandbox Code Playgroud)
...但这不会编译.我错过了什么?或者是不可能以这种方式表达事物?
LINQ使用延迟执行模型,这意味着在调用Linq运算符时不返回结果序列,而是这些运算符返回一个对象,该对象只有在枚举此对象时才会生成序列的元素.
虽然我理解延迟查询是如何工作的,但我在理解延迟执行的好处时遇到了一些麻烦:
1)我已经读过只有在你真正需要结果时执行的延迟查询才会有很大的好处.那么这个好处是什么?
2)延迟查询的其他优点是,如果您定义一次查询,那么每次枚举结果时,如果数据发生更改,您将得到不同的结果.
a)但是从下面的代码中可以看出,我们能够实现相同的效果(因此,每次枚举资源时,如果数据发生变化,我们会得到不同的结果),即使不使用延迟查询:
List<string> sList = new List<string>( new[]{ "A","B" });
foreach (string item in sList)
Console.WriteLine(item); // Q1 outputs AB
sList.Add("C");
foreach (string item in sList)
Console.WriteLine(item); // Q2 outputs ABC
Run Code Online (Sandbox Code Playgroud)
3)延期执行是否还有其他好处?
以下片段编译,但我希望它等待任务结果,而不是给我一个List<Task<T>>
.
var foo = bars.Select(async bar => await Baz(bar)).ToList()
Run Code Online (Sandbox Code Playgroud)
正如这里指出的,你需要使用Task.WhenAll
:
var tasks = foos.Select(async foo => await DoSomethingAsync(foo)).ToList();
await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)
但评论指出,不需要内部async
和await
内部Select()
:
var tasks = foos.Select(foo => DoSomethingAsync(foo)).ToList();
Run Code Online (Sandbox Code Playgroud)
这里有一个类似的问题,有人试图在其中使用异步方法Where()
.
因此async
,await
在LINQ语句中是合法的语法,但它什么都不做或者它有特定的用途?
我正在尝试将数据访问同步查询转换为异步查询,到目前为止,除了选择return的列表之外,我都进行了转换IQueryable<T>
。
到目前为止,这是我所做的:
[Dependency]
public SampleContext db { get; set; }
public async System.Threading.Tasks.Task<Profile> Add(Profile item)
{
db.Profiles.Add(item);
await db.SaveChangesAsync();
return item;
}
public async System.Threading.Tasks.Task<Profile> Get(string id)
{
return await db.Profiles.AsNoTracking().Where(i => i.Id == id).FirstOrDefaultAsync();
}
public async System.Threading.Tasks.Task Remove(string id)
{
Profile item = db.Profiles.Find(id);
item.IsDeleted = 1;
db.Entry(item).State = EntityState.Modified;
await db.SaveChangesAsync();
}
public async System.Threading.Tasks.Task<bool> Update(Profile item)
{
db.Set<Profile>().AddOrUpdate(item);
await db.SaveChangesAsync();
return true;
}
Run Code Online (Sandbox Code Playgroud)
上面的代码运行良好,我被困在转换这段代码:
public IQueryable<Profile> GetAll()
{
return db.Profiles.AsNoTracking().Where(i => i.IsDeleted == 0); …
Run Code Online (Sandbox Code Playgroud) 阅读本文后: 在Parallel.ForEach中嵌套等待
我试着做以下事情:
private static async void Solution3UsingLinq()
{
var ids = new List<string>() { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
var customerTasks = ids.Select(async i =>
{
ICustomerRepo repo = new CustomerRepo();
var id = await repo.getCustomer(i);
Console.WriteLine(id);
});
}
Run Code Online (Sandbox Code Playgroud)
出于某种原因,这不起作用......我不明白为什么,我认为有一个僵局,但我不确定......