0

私は録音アプリケーションに取り組んでおり、毎秒 10 ~ 15 のスクリーンショットを取得できます。問題は、スクリーンショットのキューが RAM に蓄積されてユーザーのメモリを消費しないように、すべての画像を十分に高速に保存することです。

現在、画像を順番に保存してからガベージを収集する2つのスレッドを使用してこれを行うことができます。

while (true)
{
    bmp = null;

    Dispatcher.Invoke(new Action(delegate()
    {
        if (images.Count > 0)
        {
            bmp = images[0];
            images.RemoveAt(0);
        }
    }));

    if (bmp != null)
    {
        bmp.Save("frames\\" + framesImagesIndex++ + ".png", ImageFormat.Png);
        bmp.Dispose();
        bmp = null;
        GC.Collect();
    }

    Thread.Sleep(10);
}

これの問題は、非常に CPU を集中的に使用することです。そのため、能力の低いシステムでは動作しないと思います。この方法は、私の 3.31 GHz プロセスで 30 CPU を使用します。

すべての画像を 1 つのファイルに書き込み、ビットマップのビットをロックしてバイトのみを書き込むように設定すると、CPU を約 17 に軽減できます。

byte[] rgbValues;

IntPtr ptr;

System.Drawing.Rectangle rect;

System.Drawing.Imaging.BitmapData bmpData;

System.Drawing.Imaging.PixelFormat pxf;


pxf = System.Drawing.Imaging.PixelFormat.Format24bppRgb;

//using(FileStream fs = new FileStream("frames.data", FileMode.OpenOrCreate, FileAccess.Write))
while (true)
{
    bmp = null;

    Dispatcher.Invoke(new Action(delegate()
    {
        if (images.Count > 0)
        {
            bmp = images[0];
            images.RemoveAt(0);
        }
    }));


    rect = new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height);
    bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, pxf);

    ptr = bmpData.Scan0;

    rgbValues = new byte[bmpData.Stride * bmp.Height];

    Marshal.Copy(ptr, rgbValues, 0, rgbValues.Length);

    fs.Write(rgbValues, 0, rgbValues.Length);

    bmp.UnlockBits(bmpData);

    bmp.Dispose();
    bmp = null;
    GC.Collect();
}

この方法は CPU の問題に役立ちますが、十分に高速ではないためです。画像のキューが蓄積され、RAM が過負荷になるため、両方の問題を解決するために他に何ができるかわかりません。

他に利用可能な方法はありますか?

4

1 に答える 1

0

まず、a でwhileループを使用すると、Thread.Sleep(x);非常に CPU を集中的に使用GC.Collect()し、新しいインスタンスを頻繁に呼び出すことになります。むしろ、スレッドの使用を検討する必要があります。

Action action;
public void Main()
{
action = new Action(delegate()
{
    if (images.Count > 0)
    {
        bmp = images[0];
        images.RemoveAt(0);
    }
});
Thread thread = new Thread(SaveBitmap());
thread.Start();
thread.Priority =  ThreadPriority.Highest
}
public void SaveBitmap()
{
    Dispatcher.Invoke(action);

if (bmp != null)
{
    bmp.Save("frames\\" + framesImagesIndex++ + ".png", ImageFormat.Png);
    bmp.Dispose();
    bmp = null;
}
}

上記を使用するか、少なくともいくつかの部分を統合してみてください。

于 2013-10-01T23:59:13.770 に答える