我首先要说的是,我目前正在学习有关多线程的信息,因此可能并非我所讲的全部都是正确的-请随时根据需要纠正我。我对异步和等待有一定的了解。
我的基本目标如下: 我有一段代码,目前大约需要3秒钟。我正在尝试在方法的开头加载一些数据,这些数据将在结尾处使用。我的计划是从一开始就将数据加载到其他线程上-允许其余代码独立执行。然后,在需要数据时,如果未加载数据,代码将等待。到目前为止,正如我所描述的,这一切似乎都工作正常。
我的问题与当我在并行for循环中不等待而调用异步方法时发生什么情况有关。
我的代码遵循以下结构:
public void MainCaller()
{
List<int> listFromThread = null;
var secondThread = Task.Factory.StartNew(() =>
{
listFromThread = GetAllLists().Result;
});
//Do some other stuff
secondThread.Wait();
//Do not pass this point until this thread has completed
}
public Task<List<int>> GetAllLists()
{
var intList = new List<int>(){ /*Whatever... */};
var returnList = new List<int>();
Parallel.ForEach(intList, intEntry =>
{
var res = MyMethod().Result;
returnList.AddRange(res);
});
return Task.FromResult(returnList);
}
private async Task<List<int>> MyMethod()
{
var myList = await obtainList.ToListAsync();
}
请注意,Parallel for Loop会调用async方法,但由于它本身不是异步的,所以不会等待它。
这是在其他地方使用的方法,因此它是异步的是有效的。我知道一个选择是复制此方法的副本,该副本不是异步的,但我试图了解此处将发生什么。
我的问题是,我可以确定到达secondThread.Wait();
后,执行的异步部分将完成。例如,将等待知道等待异步部分完成,还是将异步弄乱等待,或者它将无缝地协同工作?
在我看来,可能没有等待对MyMethod的调用,但是MyMethod中存在等待,并行的for循环是否可以在等待的调用完成之前继续执行?
然后我认为,由于它是通过引用分配的,因此一旦分配完成,该值将是正确的结果。
这使我认为,只要等待知道等待异步完成,就不会有问题-因此就是我的问题。
我想这与我对任务缺乏理解有关?
我希望这很清楚吗?
答案 0 :(得分:1)
在您的代码中,没有部分被非常规地执行。
最终结果是您的代码完全同步执行。唯一的并行性是在Parallel.For循环中引入的。
提示:与该主题有关的有用线程:Using async/await for multiple tasks
此外,您的代码包含一个严重的错误: 由Parallel.For循环创建的每个Task最终都将通过调用AddRange将其部分列表添加到ReturnList中。 'AddRange'不是线程安全的,因此您需要具有某种同步机制(例如'Lock'),否则您的ReturnList可能会损坏或不包含所有结果。另请参阅:Is the List<T>.AddRange() thread safe?