C#禁用USB ReadPipe的垃圾收集 [英] C# Disable garbage collection for USB ReadPipe

查看:72
本文介绍了C#禁用USB ReadPipe的垃圾收集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用FTDI的D3XX.NET从USB端口收集数据.收集数据,然后将其发送到快速傅立叶变换以绘制频谱.即使您错过了一些数据,它也可以正常工作.你不知道但是,如果您随后希望将此数据发送到音频输出组件,则会注意到数据丢失.这就是我的问题所在. 收集数据,然后将其发送到音频设备.所有数据包都在所需的时间范围内达到目标.但是,音频正在丢弃显示的数据.这是音频输出中正弦波的图片:

I am attempting to collect data from a USB port using D3XX.NET from FTDI. The data is collected and then sent to a fast fourier transform for plotting a spectrum. This works fine, even if you miss some data. You can't tell. However, if you then want to send this data to an audio output component, you will notice data missing. This is where my problem appears to be. The data is collected and then sent to the audio device. All packets are making it within the time span needed. However, the audio is dropping data it appears. Here is a picture of what a sine wave looks like at the output of the audio:

您可以看到开始时缺少一些数据,并且似乎在末尾缺少了一个完整的周期.这只是一个例子,它一直在变化.有时似乎数据不存在. 我已经遍及整个处理链,并且我很确定声音的数据包正在制作中. 从那以后我就使用了JetBrains性能分析器.我发现的是以下内容:ReadPipe方法花费8.5毫秒,这恰好是您希望读取的内容.到目前为止,一切都很好. ReadPipe命令完成后,您需要0.5毫秒来执行另一个ReadPipe,否则您将丢失一些数据.查看探查器的输出,我看到以下内容:

You can see that some data is missing at the beginning and it seems a whole cycle is missing near the end. This is just one example, it changes all the time. Sometimes it appears that the data is just not there. I have gone through the whole processing chain and i'm pretty sure the data packets for the sound are making it. I have since used JetBrains performance profiler. What I have found is the following: The ReadPipe method takes 8.5ms which is exactly what you expect the read to take. So far so good. Once the ReadPipe command is finished, you have 0.5ms to do another ReadPipe or you will loose some data. Looking at the profiler output I see this:

ReadPipe花费8.5ms,然后有一个条目用于垃圾回收,平均花费1.6ms.如果确实偶尔发生这种情况,那么我已经丢失了一些数据.

The ReadPipe takes 8.5ms and then there is this entry for garbage collection which on average takes 1.6ms. If this is indeed occurring even occasionally, then I have lost some data.

下面是代码:它是后台工作人员:

So here is the code: It is a backgroundworker:

    private void CollectData(object sender, DoWorkEventArgs e)
    {
        while (keepGoing)
        {
            ftStatus = d3xxDevice.ReadPipe(0x84, iqBuffer, 65536, ref bytesTransferred); //read IQ data - will get 1024 pairs - 2 bytes per value

            _waitForData.Set();
        }
    }

waithandle向另一个线程表示数据可用. 那么GC是造成数据丢失的原因吗?如果是这样,我该如何避免呢? 谢谢!

The waithandle signifies to the other thread that data is available. So is the GC the cause of the lost data? And if so, how can I avoid this? Thanks!

推荐答案

如果可以确认内存还没用完,可以尝试将GCSettings.LatencyMode设置为GCLatencyMode.SustainedLowLatency.除非您的内存不足,否则这将防止发生某些阻塞垃圾收集.查看有关延迟的文档模式以了解更多详细信息和限制.

If you can confirm that you aren't running out of memory, you could try setting GCSettings.LatencyMode to GCLatencyMode.SustainedLowLatency. This will prevent certain blocking garbage collections from occurring, unless you're low on memory. Check out the docs on latency modes for more details and restrictions.

如果对于您的用例而言,垃圾收集仍然具有破坏性,并且您正在使用.NET 4.6或更高版本,则可以尝试调用

If garbage collection is still too disruptive for your use case and you're using .NET 4.6 or later, you may be able to try calling GC.TryStartNoGCRegion. This method will attempt to reserve enough memory to allocate up to the amount specified, and block GC until you've exhausted the reservation. If your memory usage is fairly consistent, you might be able to get away with passing in a large enough value to accommodate your application's usage, but there's no guarantee that the call will succeed.

如果您使用的旧版.NET不支持这两个版本,则可能不走运.如果这是一个GUI应用程序(由事件处理程序判断,它看起来像),那么您对分配的控制就不够.

If you're on an older version of .NET that doesn't support either of these, you're probably out of luck. If this is a GUI application (which it looks like, judging by the event handler), you don't have enough control over allocations.

要考虑的另一件事是,对于不能容忍中断的应用程序,C#并不是真正的正确工具.如果您熟悉编写本机代码,则可以在非托管线程上执行对时间敏感的工作.据我所知,这是唯一可靠的解决方案,尤其是当您的应用程序要在最终用户计算机上运行时.

Another thing to consider is that C# isn't really the right tool for applications that can't tolerate disruptions. If you're familiar with writing native code, you could perform your time sensitive work on an un-managed thread; as far as I'm aware, this is the only reliable solution, especially if your application is going to run on end-user machines.

这篇关于C#禁用USB ReadPipe的垃圾收集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆