I'm using mvc 5 and follow this sample to generate an array Task.
我正在使用mvc 5,并跟随这个示例来生成一个数组任务。
I'm sure database contains 1 row at least with the query. I think I'm getting the problem with Task, because it threw me error message
我确信数据库至少包含一行查询。我认为我在任务中遇到了问题,因为它给了我错误信息
The tasks argument included a null value.
tasks参数包含一个空值。
when I tried:
当我试着:
// I'm sure `cg` was not null and `type` was not empty
var cg = new List<string>();
var type = "";
var db = new MyDbContext();
var list = new List<TopicViewModels>();
if (cg != null && cg.Count > 0)
{
var tasks = new Task<List<TopicViewModels>>[13];
byte i = 0;
while (i < cg.Count)
{
string _cg = cg[i];
tasks[i] = Task.Run(async () =>
{
return await db.Topics.Where(m => m.Type == type && m.Category == _cg)
.ToListAsync();
});
i++;
}
var continuation = Task.WhenAll(tasks); //the tasks argument included a null value
// never go to this loop...
foreach (var topics in continuation.Result)
{
topics.ForEach(x => list.Add(x));
}
}
I've set breakpoint to check array tasks
, tasks[0]
was not null. It's appened correctly.
我设置了断点来检查数组任务,任务[0]不是空的。这是正确的动作。
Can you explain me why?
你能解释一下为什么吗?
UPDATE: (based on @YacoubMassad comment)
更新:(基于@YacoubMassad注释)
await Task.WhenAll(tasks); //same error here...
//never go to this loop, too...
foreach (var task in tasks)
{
//
}
UPDATE 2: (based on @DavidPine answer)
更新2:(基于@DavidPine的回答)
if (cg != null && cg.Count > 0)
{
var tasks = new List<Task<List<TopicViewModels>>>();
cg.ForEach(x =>
{
tasks.Add(Task.Run(async () =>
{
return await db.Topics.Where(m => m.Type == type && m.Category == x)
.ToListAsync();
}));
});
foreach (var topics in await Task.WhenAll(tasks.ToArray()))
{
topics.ForEach(x => list.Add(x));
}
}
2 个解决方案
#1
3
There are a few issues here:
这里有几个问题:
1. When working with Task
or Task<T>
always use async / await
if it is available, i.e.; you're working with .NET 4.5.
1。当处理任务或任务
2. When you invoke Task.WhenAll(tasks)
, it is possible that there is a task in the array that is null. You need to check that for that and handle it correctly.
2。当您调用task .When all (tasks)时,数组中有一个任务可能是空的。您需要对此进行检查并正确处理。
3. You need to await the when all to ensure the work is done, await Task.WhenAll(tasks)
.
3所示。你需要等待所有的时间来确保工作完成,等待任务完成。
var cg = new List<string>();
var type = "";
var db = new MyDbContext();
var list = new List<TopicViewModels>();
if (cg != null && cg.Count > 0)
{
var tasks = new Task<List<TopicViewModels>>[13];
byte i = 0;
while (i < cg.Count)
{
string _cg = cg[i];
tasks[i] = Task.Run(async () =>
{
// Isn't it possible that the where clause filters out and returns null?
return await db.Topics
.Where(m => m.Type == type && m.Category == _cg)
.ToListAsync();
});
i++;
}
// Use await keyword to ensure that work is done
var continuation = await Task.WhenAll(tasks.Where(t => t != null).ToArray());
// never go to this loop...
foreach (var topics in continuation.Result)
{
topics.ForEach(x => list.Add(x));
}
}
#2
3
There are a couple of problems in your code.
在您的代码中有几个问题。
First of all, you using naturally asynchronous methods that query a database, you don't need to execute then on a threadpool thread, that's redundant, especially in ASP.NET which already uses thread pool threads to serve requests.
首先,使用查询数据库的自然异步方法,不需要在threadpool线程上执行,这是多余的,特别是在ASP中。NET,它已经使用线程池线程来服务请求。
Second of all, you're not awaiting on the task returned by Task.WhenAll
, you're synchronously blocking when iterating in the foreach
loop using Task.Result
.
其次,您没有等待任务返回的任务。当您使用Task.Result在foreach循环中迭代时,您正在同步阻塞。
You're code should be:
你的代码应该是:
var queryTasks = cg.Select(cg => db.Topics.Where(m => m.Type == type && m.Category == cg).ToListAsync());
return await Task.WhenAll(queryTasks);
Do note that that EF DbContext
is not thread-safe, and doesn't allow concurrent operations to be executed on it. If that is the case here, you'll need to await
each query independently.
请注意,EF DbContext不是线程安全的,并且不允许在其上执行并发操作。如果是这样,您需要独立地等待每个查询。
#1
3
There are a few issues here:
这里有几个问题:
1. When working with Task
or Task<T>
always use async / await
if it is available, i.e.; you're working with .NET 4.5.
1。当处理任务或任务
2. When you invoke Task.WhenAll(tasks)
, it is possible that there is a task in the array that is null. You need to check that for that and handle it correctly.
2。当您调用task .When all (tasks)时,数组中有一个任务可能是空的。您需要对此进行检查并正确处理。
3. You need to await the when all to ensure the work is done, await Task.WhenAll(tasks)
.
3所示。你需要等待所有的时间来确保工作完成,等待任务完成。
var cg = new List<string>();
var type = "";
var db = new MyDbContext();
var list = new List<TopicViewModels>();
if (cg != null && cg.Count > 0)
{
var tasks = new Task<List<TopicViewModels>>[13];
byte i = 0;
while (i < cg.Count)
{
string _cg = cg[i];
tasks[i] = Task.Run(async () =>
{
// Isn't it possible that the where clause filters out and returns null?
return await db.Topics
.Where(m => m.Type == type && m.Category == _cg)
.ToListAsync();
});
i++;
}
// Use await keyword to ensure that work is done
var continuation = await Task.WhenAll(tasks.Where(t => t != null).ToArray());
// never go to this loop...
foreach (var topics in continuation.Result)
{
topics.ForEach(x => list.Add(x));
}
}
#2
3
There are a couple of problems in your code.
在您的代码中有几个问题。
First of all, you using naturally asynchronous methods that query a database, you don't need to execute then on a threadpool thread, that's redundant, especially in ASP.NET which already uses thread pool threads to serve requests.
首先,使用查询数据库的自然异步方法,不需要在threadpool线程上执行,这是多余的,特别是在ASP中。NET,它已经使用线程池线程来服务请求。
Second of all, you're not awaiting on the task returned by Task.WhenAll
, you're synchronously blocking when iterating in the foreach
loop using Task.Result
.
其次,您没有等待任务返回的任务。当您使用Task.Result在foreach循环中迭代时,您正在同步阻塞。
You're code should be:
你的代码应该是:
var queryTasks = cg.Select(cg => db.Topics.Where(m => m.Type == type && m.Category == cg).ToListAsync());
return await Task.WhenAll(queryTasks);
Do note that that EF DbContext
is not thread-safe, and doesn't allow concurrent operations to be executed on it. If that is the case here, you'll need to await
each query independently.
请注意,EF DbContext不是线程安全的,并且不允许在其上执行并发操作。如果是这样,您需要独立地等待每个查询。