只有最后一个任务运行!

5

我急需找到解决我的问题的方法。

以下是生成List<AccountContactView>中每个项目的不同任务的代码。

List<AccountContactViewModel> selectedDataList
    = DataList.Where(
        dataList => (bool) dataList.GetType()
                                   .GetProperty("IsChecked")
                                   .GetValue(dataList, new object[0]) == true
      ).ToList();

this.IsEnabled = false;

Task validateMarked = Task.Factory.StartNew(() =>
{
    foreach (AccountContactViewModel viewModel in selectedDataList)
    {
        if (viewModel != null)
        {
            Task validate = Task.Factory.StartNew(
                () => ValidateAccount(viewModel),
                (TaskCreationOptions)TaskContinuationOptions.AttachedToParent);
        }
    }
});

validateMarked.ContinueWith(x => this.IsEnabled = true);

现在我的问题是,当它运行时,它只对数组中的最后一个项目运行。有关我做错了什么的任何想法吗?
我不想使用Parallel.ForEach,因为它不能提供并行性所需的效果,以根据每个任务的完成情况增加进度条。

6
每天几乎都有人在SO上问这个问题。你是在循环内部关闭了一个循环变量。详情请参见http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx。 - Eric Lippert
小细节,但是如果你只是在foreach中枚举DataList查询结果的话,就没有必要调用.ToList()了。 - dlev
1个回答

9

这可能是一个lambda作用域问题。

在将viewModel传递给StartNew方法之前,您是否尝试将其分配给本地变量?

...
Task validateMarked = Task.Factory.StartNew(() =>
{
    foreach (AccountContactViewModel viewModel in selectedDataList)
    {
        var localViewModel = viewModel;
        if (localViewModel != null)
        {
            Task validate = Task.Factory.StartNew(
                () => ValidateAccount(localViewModel),
                (TaskCreationOptions)TaskContinuationOptions.AttachedToParent);
        }
    }
});
...

兄弟,你为什么要将viewModel分配给本地变量?我已经看到Resharper多次抱怨这个问题了。顺便点个赞。 - Sachin Kainth
1
请查看原问题的评论中的Eric Lippert文章。他解释得很好。谢谢。 - marto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接