问题
I have the following method inside my asp.net mvc-5 web application :-
public async Task <List<Details>> Get()
{
Parallel.ForEach(resourcesinfo.operation.Details,new ParallelOptions { MaxDegreeOfParallelism = 20 }, (c) =>
{
ResourceAccountListInfo resourceAccountListInfo = new ResourceAccountListInfo();
using (WebClient wc = new WebClient())
{
string url = currentURL + "resources/" + c.RESOURCEID + "/accounts?AUTHTOKEN=" + pmtoken;
string tempurl = url.Trim();
var json = await wc.DownloadStringTaskAsync(tempurl);
resourceAccountListInfo = JsonConvert.DeserializeObject<ResourceAccountListInfo>(json);
}
//code goes here
but I am getting this error :-
The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier
so can anyone adivce on this please ?
回答1:
Parallel.ForEeach
is not designed to work with asynchronous functions, you need to use more modern classes like the ones in TPL Dataflow. You get it by installing the NuGet package to your project Microsoft.Tpl.Dataflow. You could recreate your previous code as
private const int MAX_PARALLELISM = 20
public async Task <List<Details>> Get()
{
var block = new ActionBlock<Entry>(async (c) =>
{
ResourceAccountListInfo resourceAccountListInfo = new ResourceAccountListInfo();
using (WebClient wc = new WebClient())
{
string url = currentURL + "resources/" + c.RESOURCEID + "/accounts?AUTHTOKEN=" + pmtoken;
string tempurl = url.Trim();
var json = await wc.DownloadStringTaskAsync(tempurl);
resourceAccountListInfo = JsonConvert.DeserializeObject<ResourceAccountListInfo>(json);
}
//code goes here
}
,new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = MAX_PARALLELISM
});
foreach(var entry in resourcesinfo.operation.Details)
{
await block.SendAsync(entry);
}
block.Complete();
await block.Completion;
//More code here
}
After thinking for a bit, here is a slightly more complicated version that does the entire pipeline from reading the records in to returning a result from Get()
private const int MAX_PARALLELISM = 20
public async Task<List<Details>> Get()
{
List<Details> result = new List<Details>();
var getRecordBlock = new TransformBlock<Entry, ResourceAccountListInfo>(async (c) =>
{
ResourceAccountListInfo resourceAccountListInfo = new ResourceAccountListInfo();
using (WebClient wc = new WebClient())
{
string url = currentURL + "resources/" + c.RESOURCEID + "/accounts?AUTHTOKEN=" + pmtoken;
string tempurl = url.Trim();
var json = await wc.DownloadStringTaskAsync(tempurl);
resourceAccountListInfo = JsonConvert.DeserializeObject<ResourceAccountListInfo>(json);
}
return resourceAccountListInfo;
}
, new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = MAX_PARALLELISM
});
//Defaults to MaxDegreeOfParallelism = 1
var addToListBlock = new ActionBlock<ResourceAccountListInfo>(info =>
{
Details detail = TurnResourceAccountListInfoInToDetails(info);
result.Add(detail);
});
getRecordBlock.LinkTo(addToListBlock, new DataflowLinkOptions { PropagateCompletion = true});
foreach (var entry in resourcesinfo.operation.Details)
{
await getRecordBlock.SendAsync(entry);
}
getRecordBlock.Complete();
await addToListBlock.Completion;
return result;
}
来源:https://stackoverflow.com/questions/38077791/can-not-use-await-inside-a-parallel-foreach-error-the-await-operator-can