一个比较简单的方法是使用MemoryMappedFile(内存映射,http://msdn.microsoft.com/zh-cn/library/system.io.memorymappedfiles.memorymappedfile(v=vs.100).aspx)。好处是免费使用了操作系统缓存机制。
坏处是不容易重写到Linux等。

解决方案 »

  1.   

    实在看不出楼主的需求与MemoryMappedFile有什么关联
      

  2.   


    我也没看出来。有些回答是瞎灌水的。反正闲着没事,进入一个问题,一看有个高等级的用户回答了问题,于是复制粘贴,或者鹦鹉学舌下。内存映射是虚拟内存的一种运用技术。
    优点之一在于映射的内容可以延迟读取。内存映射建立在VMM(虚拟内存管理器)之上。VMM保证对还没有读取的内容进行加载(以一个页面4K为单位)。内核支持和4K页面意味快速读取和有效的缓存。
    优点之二在于,如果内存紧张,VMM可以自动释放加载过的缓存。
    其他优点还包括,大文件支持,使用方便等。
    进一步可阅读(英文):http://msdn.microsoft.com/zh-cn/library/ms810613.aspx下面的代码示范使用MemoryMappedFile来进行绘图(需DotNet4.0),示范数据为300兆的数据:public partial class Form1 : Form
    {
        public Form1()
        {
            //InitializeComponent();
            string filename = "c:\\temp\\example.dat";
            if (!File.Exists(filename))
            {
                MessageBox.Show("First run. Will create 300M example data file: " + filename);
                GenerateData(filename); 
            }
            this.memoryMappedFile = MemoryMappedFile.CreateFromFile(filename);
            this.scrollbar = new HScrollBar()
            {
                Height = 32,
                Dock = DockStyle.Bottom,
                Maximum = (int)(new FileInfo(filename).Length / 4),
            };
            this.scrollbar.ValueChanged += (sender, e) => this.Invalidate(invalidateChildren: false);
            this.Controls.Add(scrollbar);
            this.DoubleBuffered = true;
            this.Size = new Size(800, 600);
        }
        ScrollBar scrollbar;
        MemoryMappedFile memoryMappedFile;    protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            int sampling = 100;
            int start = Math.Min(this.scrollbar.Value, this.scrollbar.Maximum - sampling);
            e.Graphics.DrawCurve(Pens.Black, GetPoints(start, sampling));
            e.Graphics.DrawString(start.ToString("n0"), this.Font, Brushes.DarkBlue, new Point(200, 15));
        }    private PointF[] GetPoints(int start, int count)
        {
            List<PointF> points = new List<PointF>(count);
            using (var viewStream = memoryMappedFile.CreateViewStream(start * sizeof(float), count * sizeof(float)))
            using (var reader = new BinaryReader(viewStream))
            {
                for (int i = 0; i < count; i++)
                {
                    float x = i * this.ClientRectangle.Width / 100;
                    float y = reader.ReadSingle() * this.ClientRectangle.Height;
                    points.Add(new PointF(x, y));
                }
            }
            return points.ToArray();
        }    private void GenerateData(string outputFile = "c:\\temp\\my.dat", int count = 75 * 1024 * 1024)
        {
            Random random = new Random(123);
            if (!Directory.Exists(Path.GetDirectoryName(outputFile))) Directory.CreateDirectory(Path.GetDirectoryName(outputFile)); 
            using (BinaryWriter writer = new BinaryWriter(new FileStream(outputFile, FileMode.Create)))
            {
                float last = 0.5f;
                for (int i = 0; i < count; i++)
                {
                    last = last + (float)(random.NextDouble() - 0.5) / 20;
                    last = Math.Max(0, Math.Min(last, 1));
                    writer.Write(last);
                }
            }
        }
    }
      

  3.   

    首先,我无法确定楼主说的数据源是不是文件。
    其次,我觉得楼主需要的是多线程,而不是实时加载数据。
    再次,恕我愚昧,我实在无法理解MemoryMappedFile在楼主的需求中相对于FileStream有什么优点。
      

  4.   

    我的数据时二进制文件。谁有类似的Demo啊!感谢了!
      

  5.   


    我想问下,如何判断在滚动条到达指定的位置时继续加载。我想让内存中只保存需要显示的一部分数据。这个问题分为两方面,一个是显示的部分,按需显示。
    另外一个就是你需要根据坐标建立一个数据结构,比如根据坐标做hash,保证可以快速检索到指定范围的数据,而不是每次都要全部搜索一遍。
      

  6.   


    我想问下,如何判断在滚动条到达指定的位置时继续加载。我想让内存中只保存需要显示的一部分数据。这个问题分为两方面,一个是显示的部分,按需显示。
    另外一个就是你需要根据坐标建立一个数据结构,比如根据坐标做hash,保证可以快速检索到指定范围的数据,而不是每次都要全部搜索一遍。
    你说的有点深奥了我理解不了。我现在每次异步读取固定长度的数据,然后绘制成图,滚动条左右拖动可以观察,我想让滚动条拖动到大于导入内容的80%的时候继续异步读取。依次类推,每到大于80%的时候异步读取。但是我不知道怎么判断是否大于80%;我现在的滚动条最大值是文件的长度!