我正在绘制可视化的WaveIn记录数据,仅用于测试目的,以查看数据的正确性。 如您所见,我的机制是:
1)一些WaveIn线程(不包括在内)通过带有音频缓冲区的委托戳此Form。
2)背景工作者获取更新的音频数据,绘制位图 完成后,它会报告进度,并且该本地表单线程中的句柄只需调用WM_PAINT即可用新图片更新PictureBox背景。
object localLock = new object();
Bitmap soundGraphImage;
private void soundGrapher_DoWork(object sender, DoWorkEventArgs e) {
while(are.WaitOne())
{
if (soundGrapher.CancellationPending) {
e.Cancel = true;
return;
}
if (audioData == null || audioData.Length == 0) continue;
soundGraphImage = new Bitmap(graphWidth, graphHeight); <----- this one
Graphics g = Graphics.FromImage(soundGraphImage);
lock (localLock)
{
#region Draw sound
if (audioParms.nChannels > 1) { Vfw_MessageOut("More than 1 channel"); return; }
int currentPos = 1;
int accu = 0;
int x = 1;
int maxValue = 0;
int baseY = soundGraph.Height / 2;
int bytes = audioParms.wBitsPerSample / 8;
int portion = (int)Math.Round(1.0 * audioData.Length / bytes / soundGraph.Width, MidpointRounding.ToEven);
switch (bytes)
{
case 1: maxValue = Byte.MaxValue; break;
case 2: maxValue = Int16.MaxValue; break;
case 4: maxValue = Int32.MaxValue; break;
}
int halfValue = maxValue / 2;
double coeff = multiPlyer * baseY / halfValue;
for (int i = 0; i < audioData.Length; i = i + bytes)
{
if (currentPos == portion)
{
accu = (int)(accu / portion);
g.DrawLine(Pens.White, new Point(x, baseY),
new Point(x, baseY - (int)(coeff * accu)));
currentPos = 1;
i = i - bytes;
x++;
}
else
{
currentPos++;
switch (bytes)
{
case 1: accu += audioData[i] - halfValue; break;
case 2: accu += BitConverter.ToInt16(audioData, i); break;
case 4: accu += BitConverter.ToInt32(audioData, i); break;
}
}
}
#endregion
}
g.Dispose();
soundGrapher.ReportProgress(0);
}
}
private void soundGrapher_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
}
private void soundGrapher_ProgressChanged(object sender, ProgressChangedEventArgs e) {
soundGraph.Invalidate();
}
问题出在位图中。此代码导致内存泄漏。 请帮我避免这个问题。
更新
是的,解决方案很简单,只需对其进行处置即可。 当然,靠我自己,但是我仍然有一个更大的问题,这 当位图进入阶段时,位图就在我的栈顶 “堆栈溢出”。但是无论如何这是GC的错。 控制这样的事情。回调每秒仅戳一次。 以前从未在每个位图上调用Dispose 项目。
答案 0 :(得分:1)
更新
“使用”将破坏位图,但我仍然需要它 抽奖。
哦,亲爱的...
在每次重新创建它时,您仍然都必须Dispose
进行一些操作……
我可以建议
soundGraphImage?.Dispose();
soundGraphImage = new Bitmap(graphWidth, graphHeight);
原始
在任何可以支持它的东西上都使用using
语句,遵守该规则,并且(在这种情况下)您可能是对的。
在这方面,您至少应该在以下方面实现using
:-
using(var soundGraphImage = new Bitmap(graphWidth, graphHeight))
{
}
在其他对象上,例如Graphics
只是为了保持一致
其他资源
using statement (C# Reference)
提供了一种方便的语法,可确保正确使用 可分配对象。
using语句获取一个或多个资源,执行一个 语句,然后处置资源。
提供了一种释放非托管资源的机制。