使用线程时内存不足异常

本文关键字:内存不足 异常 线程 | 更新日期: 2023-09-27 18:05:10

我有以下算法,

private void writetodb()
{
    using(var reader = File.OpenRead("C:'Data.csv");
    using(var parser = new TextFieldParser(reader))
    { 
        //Do some opeartions
        while(!parser.EndOfData)
        {
            //Do operations
            //Take 500 rows of data and put it in dataset
            Thread thread = new thread(() => WriteTodb(tablename, set));
            thread.Start();
            Thread.Sleep(5000);
        }
    }
}
public void WriteTodb(string table, CellSet set)
{
    //WriteToDB
    //Edit: This statement will write to hbase db in hdinsight
    hbase.StoreCells(TableName, set);
}

此方法在 500mb数据之前工作得很好,但在此之后它失败了,说Out of memory exception .

我很确定这是因为线程,但使用线程是强制性的,我不能改变架构。
有没有人能告诉我在上面的程序中,我必须在线程编程中做哪些修改来避免内存异常?

使用线程时内存不足异常

首先,我不明白你说的关于线程:

我不得不在线程编程中使上述程序避免内存例外。

如果您使用TPL,您将使用线程编程,正如已经建议的那样。如果你不能理解Thread类,你真的不必使用它。您说您的代码是C# 4.0,因此TPL是您的选项。你可以这样做(非常简单的方法):

List<Task> tasks  = new List<Task>();
while(!parser.EndOfData)
{
    tasks.Add(Task.Run(() => WriteTodb(tablename, set)));
}
Task.WaitAll(tasks.ToArray());

TPL引擎将使用默认的TaskScheduler类,它使用内部ThreadPool,并可以在服务器上设置资源级别。

另外,我看到你正在使用微软的HBase客户端,它有async方法:

public async Task StoreCellsAsync(string table, CellSet cells)
{
}
因此,您可以在代码 TPL中同时使用异步方法:
List<Task> tasks  = new List<Task>();
while(!parser.EndOfData)
{
    tasks.Add(WriteTodb(tablename, set)));
}
// asynchroniously await all the writes
await Task.WhenAll(tasks.ToArray());
public async Task WriteTodb(string table,CellSet set)
{
    //WriteToDB
    //Edit: This statement will write to hbase db in hdinsight asynchroniously!
    await hbase.StoreCellsAsync(TableName, set);
}

如果,由于一些奇怪的原因,你不能使用TPL,你必须重构你的代码并编写你自己的线程调度程序:

  1. 你不必每次都为你的写创建线程,你可以重用它们。
  2. 在同一个线程内运行第二次,通常比为每个操作创建两个不同的线程快。
  3. 将文件分割成几个部分,创建写线程,循环写数据。

使用ThreadPool.QueueUserWorkItem代替每次创建新线程。参考:https://msdn.microsoft.com/en-us/library/kbf0f1ct(v=vs.110).aspx