2
 var source = new Bitmap(2000,2000);

        var sw = Stopwatch.StartNew();
        for (int i = 0; i < 10000; i++)
        {
            //var copy = new Bitmap(source);
            var copy = source.Clone() as Bitmap;

        }
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds);

コードは私のシステムで 10 ミリ秒未満で実行され、Ram の使用は同じままです。このタイマーと RAM の使用結果では、Bitmapdata のコピーはありません。

しかし、私がこれを行うとき。

        var copy2 = source.Clone() as Bitmap;

        for (int x = 0; x < copy2.Width; x++)
        {
            for (int y = 0; y < copy2.Height; y++)
            {
                copy2.SetPixel(x, y, Color.Red);
            }
        }

        // copy2 is Red
        // source is NOT!!

これはどのように可能ですか?

4

2 に答える 2

2

あなたsource 10,000回コピーされます。Clone()コンパイラはメソッド呼び出しが持つ可能性のある副作用を認識していないため、への呼び出しを最適化して取り除くことはできません。

もちろん、クローンは保持されないため、ガベージ コレクターはすぐにクローンを削除することを選択する可能性があります (おそらく、ループがまだ実行されている間)。

クローンを保持することもできます。これを試して:

var source = new Bitmap(2000, 2000);
var li = new List<Bitmap>();
var sw = Stopwatch.StartNew();
for (int i = 0; i < 10000; i++)
{
    li.Add((Bitmap)source.Clone());
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

Console.WriteLine(li.Count);
li[4321].SetPixel(1234, 123, Color.Blue);
Console.WriteLine(li[1234].GetPixel(1234, 123)); // checks if a pixel of another clone also changed to blue

編集:クローン作成はある意味で「怠惰」であるように見えます。上記のコードは非常に高速に実行され、多くのメモリを使用しません。source非常に複雑なビットマップであっても同じことが起こるように見えるので、sourceビットマップが非常に「圧縮」できる場合に起こることだけではありません。

上記のリストを作成した後li、次のコードを実行した場合:

var randomNumberGenerator = new Random();

for (int x = 0; x < 10000; ++x)
{
    for (int i = 0; i < 2000; ++i)
        for (int j = 0; j < 2000; ++j)
            li[x].SetPixel(i, j, System.Drawing.Color.FromArgb(randomNumberGenerator.Next()));
    Console.WriteLine(x);
}

アプリケーションのメモリ消費量がゆっくりと、しかし着実に増加することがわかります。

于 2013-01-24T16:58:55.993 に答える
1

最初のコードスニペットが非常に高速に実行される理由は、オプティマイザーがそれcopyが使用されていないことを確認し、それを切り取るためである可能性が非常に高くなります。内部ループを次のように変更した場合:

var copy = source.Clone() as Bitmap;
var copy2 = copy;

...コンパイラをだまして実際にILコードを生成し、ビットマップのクローンを作成する可能性があり、経過時間が長くなることがわかります。

于 2013-01-24T16:37:17.380 に答える