【问题标题】:Passing lists into a Task将列表传递给任务
【发布时间】:2012-12-01 10:15:23
【问题描述】:

我是 C# 和线程的新手,这是一个非常简单的问题,但我真的卡住了。我确实在这个网站上搜索过,但找不到与我的场景类似的答案:

我有一个方法说 Parent() 并且我创建了一个类型化列表,每次我将它传递给一个任务。我有什么时候清除列表和释放内存的问题,因为它一直在增长。我尝试在任务结束时清除列表,如果我使用 Parent 方法清除列表,则线程中的列表为空。

有人可以帮我吗?我知道这是一个非常简单的问题,但不胜感激。

    public void Parent()
    {
     List<MyType> list = new List<MyType>();
     for (int i = 0; i< N; i++)
     {
        list.Add(new MyType {Var = "blah"});

      if ( i% 10 == 0) //every tentth time we send a task out tou a thread
      {
       Task.Factory.StartNew(() => WriteToDB(new List<MyType>(list))); 
       //here I am              sending a new instance of the list

        //Task.Factory.StartNew(() => WriteToDB((list))); 
        //here I am sending same instance

        list.Clear();

         //if I clear here the list sent to the WriteToDB is empty
        //if I do not, the memory keeps growing up and crashes the app 
      }

      private void WriteToDB(List<MyType> list)
      {
       //do some calculations with the list 
       //insert into db 
       list.Clear(); 
      }
     }
   }

【问题讨论】:

  • 您能否显示完整的类定义,而且您似乎将一个方法嵌套在另一个方法中,我是类的父类..?

标签: c# multithreading c#-4.0 task-parallel-library


【解决方案1】:

你有一个关闭错误。

在新的Task 启动之前,不会执行 lambda () =&gt; WriteToDB(new List&lt;MyType&gt;(list))。 这有时会在您致电 list.Clear() 之后进行。

修复方法是在 lambda 之外捕获列表的副本:

var chunk = new List<MyType>(list);
Task.Factory.StartNew(() => WriteToDB(chunk));

list.Clear();

【讨论】:

    【解决方案2】:

    在启动线程之前创建新列表:

    var newList = new List<MyType>(list);
    Task.Factory.StartNew(() => WriteToDB(newList)); 
    list.Clear();
    

    这样,新列表在新线程开始之前就准备好了,因此立即清除原始列表是安全的。

    【讨论】:

    • 谢谢,我遇到了一个错误。这意味着父方法正在修改集合,因为任务操作仍在运行。 System.InvalidOperationException:集合已修改;枚举操作可能无法执行。在 System.Collections.Generic.List1.Enumerator.MoveNextRare() at System.Linq.Enumerable.WhereSelectListIterator2.MoveNext()
    • @Santino 嗯,一定有更多的代码你没有显示。你在某处使用Where 子句吗?
    • 不,这是我正在编写的非常简单的代码。 IDNK 什么是“where 子句”。在 Lambda 中?
    • @Santino 我真的不知道。也许在“做一些计算”部分的某个地方。我唯一可以建议的另一件事是尝试在 WriteToDB 方法中删除 list.Clear() - 你不需要,它是一个本地对象,无论如何都会被垃圾处理。
    【解决方案3】:
    if ( i% 10 == 0) //every tentth time we send a task out tou a thread
    {
       // clone your list before starting the task
       var listToProcess = new List<MyType>(list);
       list.Clear();
    
       Task.Factory.StartNew(() => WriteToDB(listToProcess)); 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-23
      • 1970-01-01
      • 2012-03-22
      • 2015-04-16
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多