我正在为WaveIn记录数据绘制可视化,只是为了测试目的,看看数据有多正确。正如你所看到的,我的机制是:
1)一些WaveIn线程(未包含)通过带有音频缓冲区的委托来插入此表单。
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();
}
问题出在位图中。此代码会导致内存泄漏。请帮我避免这个问题。
更新
是的,解决方案很简单,只需处理它即可。当然,我自己会得到它,但我仍然有一个更大的问题,这个位图在我的堆栈顶部时,它被称为"stackoverflow“的阶段。但不管怎样,都是GC的错。它应该控制这样的事情。回调每秒只触发一次..在我之前的项目中,我从来没有为每个位图调用过Dispose。
发布于 2019-03-20 07:16:41
更新
“使用”会破坏它的作用域之外的位图,但我仍然需要它来绘制。
哦天哪..。
你仍然需要Dispose
它的一些方法,因为你每次都在重新创建它……
我可以建议你。
soundGraphImage?.Dispose();
soundGraphImage = new Bitmap(graphWidth, graphHeight);
原始
总是在任何可以支持它的东西上使用using
语句,遵守这个规则,(在这种情况下)你可能是正确的。
在这方面,您至少应该在以下方面实现一个using
:
using(var soundGraphImage = new Bitmap(graphWidth, graphHeight))
{
}
而在其他对象上,如Graphics
调用,只是为了保持一致
其他资源
using statement (C# Reference)
提供了一种方便的语法来确保正确使用IDisposable对象。
语句获取一个或多个资源,执行一条语句,然后释放该资源。
提供了一种释放非托管资源的机制。
https://stackoverflow.com/questions/55250921
复制相似问题