- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在开发一个 C#、UWP 10 解决方案,它使用快速、连续的读/写循环与网络设备通信。 API 提供的 StreamSocket 似乎工作得很好,直到我意识到存在内存泄漏:累积了 Task<uint32>
。在堆中,每分钟数百个。
我是否使用普通的旧 while (true)
在 async Task
中循环,或使用 self 发布 ActionBlock<T>
使用 TPL 数据流(根据 this answer ),结果是相同的。
如果我消除从套接字读取并专注于写入,我能够进一步隔离问题:我是否使用 DataWriter.StoreAsync
方法或更直接的StreamSocket.OutputStream.WriteAsync(IBuffer buffer)
,问题依旧。此外,添加 .AsTask()
这些都没有区别。
即使垃圾收集器运行,这些Task<uint32>
永远不会从堆中移除。所有这些任务都已完成 ( RanToCompletion
),没有错误或任何其他属性值表明“尚未准备好回收”。
关于 this page 的问题似乎有提示(从托管世界到非托管世界的字节数组会阻止内存释放),但规定的解决方案似乎很明显:解决这个问题的唯一方法是用 C++/CX 编写所有通信逻辑。我希望这不是真的;当然,其他 C# 开发人员已经成功地实现了没有内存泄漏的连续高速网络通信。 Microsoft 肯定不会发布仅在 C++/CX 中没有内存泄漏的 API
编辑
根据要求,一些示例代码。我自己的代码有太多层,但是可以用 this Microsoft sample 观察到一个更简单的例子。 .我做了一个简单的修改,循环发送1000次来突出问题。这是相关代码:
public sealed partial class Scenario3 : Page
{
// some code omitted
private async void SendHello_Click(object sender, RoutedEventArgs e)
{
// some code omitted
StreamSocket socket = //get global object; socket is already connected
DataWriter writer = new DataWriter(socket.OutputStream);
for (int i = 0; i < 1000; i++)
{
string stringToSend = "Hello";
writer.WriteUInt32(writer.MeasureString(stringToSend));
writer.WriteString(stringToSend);
await writer.StoreAsync();
}
}
}
启动应用程序并连接套接字后,只有 Task<UInt32>
的实例在堆上。单击“SendHello”按钮后,有 86 个实例。第二次按下后:129 次。
编辑#2运行我的应用程序(使用紧密循环发送/接收)3 小时后,我可以看到肯定 有问题:50 万个任务实例,它们从未被 GC 处理过,以及应用程序的进程内存从最初的 46 MB 增加到 105 MB。显然这个应用程序不能无限期地运行。但是...这仅适用于在调试 模式下运行。如果我在 Release 模式下编译我的应用程序,部署并运行它,则不会出现内存问题。我可以让它整夜运行,很明显内存管理得当。结案。
最佳答案
there are 86 instances. After pressing it a 2nd time: 129 instances.
这是完全正常的。强烈暗示这里的真正问题是您不知道如何正确解释内存分析器报告。
Task 听起来是一个非常昂贵的对象,它物超所值,并且涉及一个线程,这是您可以创建的最昂贵的操作系统对象。但事实并非如此,Task 对象实际上是一个微不足道的对象。在 32 位模式下只占用 44 个字节,在 64 位模式下占用 80 个字节。真正昂贵的资源不属于 Task,线程池管理器负责处理。
这意味着您可以在对 GC 堆施加足够的压力以触发收集之前创建很多 Task 对象。大约 47,000 它们填充 32 位模式下的 gen #0 段。服务器上的数量更多,数十万个,它的段要大得多。
在您的代码片段中,任务对象是您实际创建的唯一对象。因此,您的 for(;;) 循环几乎没有循环到足以看到 Task 对象的数量减少或限制的程度。
所以这是一个常见的故事,对 .NET Framework 存在泄漏的指控,尤其是在运行数月的服务器式应用程序中大量使用的这些基本对象类型上,永远被高度夸大。反复猜测垃圾收集器总是很棘手,您通常只能通过让您的应用运行数月并且从未因 OOM 失败而获得信心。
关于c# - 为什么在循环中使用 StreamSocket 会导致内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32960197/
我是 PHP 新手。我一直在脚本中使用 for 循环、while 循环、foreach 循环。我想知道 哪个性能更好? 选择循环的标准是什么? 当我们在另一个循环中循环时应该使用哪个? 我一直想知道要
我在高中的编程课上,我的作业是制作一个基本的小计和顶级计算器,但我在一家餐馆工作,所以制作一个只能让你在一种食物中读到。因此,我尝试让它能够接收多种食品并将它们添加到一个价格变量中。抱歉,如果某些代码
这是我正在学习的一本教科书。 var ingredients = ["eggs", "milk", "flour", "sugar", "baking soda", "baking powder",
我正在从字符串中提取数字并将其传递给函数。我想给它加 1,然后返回字符串,同时保留前导零。我可以使用 while 循环来完成此操作,但不能使用 for 循环。 for 循环只是跳过零。 var add
编辑:我已经在程序的输出中进行了编辑。 该程序要求估计给定值 mu。用户给出一个值 mu,同时还提供了四个不等于 1 的不同数字(称为 w、x、y、z)。然后,程序尝试使用 de Jaeger 公式找
我正在编写一个算法,该算法对一个整数数组从末尾到开头执行一个大循环,其中包含一个 if 条件。第一次条件为假时,循环可以终止。 因此,对于 for 循环,如果条件为假,它会继续迭代并进行简单的变量更改
现在我已经习惯了在内存非常有限的情况下进行编程,但我没有答案的一个问题是:哪个内存效率更高;- for(;;) 或 while() ?还是它们可以平等互换?如果有的话,还要对效率问题发表评论! 最佳答
这个问题已经有答案了: How do I compare strings in Java? (23 个回答) 已关闭 8 年前。 我正在尝试创建一个小程序,我可以在其中读取该程序的单词。如果单词有 6
这个问题在这里已经有了答案: python : list index out of range error while iteratively popping elements (12 个答案) 关
我正在尝试向用户请求 4 到 10 之间的整数。如果他们回答超出该范围,它将进入循环。当用户第一次正确输入数字时,它不会中断并继续执行 else 语句。如果用户在 else 语句中正确输入数字,它将正
我尝试创建一个带有嵌套 foreach 循环的列表。第一个循环是循环一些数字,第二个循环是循环日期。我想给一个日期写一个数字。所以还有另一个功能来检查它。但结果是数字多次写入日期。 Out 是这样的:
我想要做的事情是使用循环创建一个数组,然后在另一个类中调用该数组,这不会做,也可能永远不会做。解决这个问题最好的方法是什么?我已经寻找了所有解决方案,但它们无法编译。感谢您的帮助。 import ja
我尝试创建一个带有嵌套 foreach 循环的列表。第一个循环是循环一些数字,第二个循环是循环日期。我想给一个日期写一个数字。所以还有另一个功能来检查它。但结果是数字多次写入日期。 Out 是这样的:
我正在模拟一家快餐店三个多小时。这三个小时分为 18 个间隔,每个间隔 600 秒。每个间隔都会输出有关这 600 秒内发生的情况的统计信息。 我原来的结构是这样的: int i; for (i=0;
这个问题已经有答案了: IE8 for...in enumerator (3 个回答) How do I check if an object has a specific property in J
哪个对性能更好?这可能与其他编程语言不一致,所以如果它们不同,或者如果你能用你对特定语言的知识回答我的问题,请解释。 我将使用 c++ 作为示例,但我想知道它在 java、c 或任何其他主流语言中的工
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
我是 C 编程和编写代码的新手,以确定 M 测试用例的质因数分解。如果我一次只扫描一次,该功能本身就可以工作,但是当我尝试执行 M 次时却惨遭失败。 我不知道为什么 scanf() 循环有问题。 in
这个问题已经有答案了: JavaScript by reference vs. by value [duplicate] (4 个回答) 已关闭 3 年前。 我在使用 TSlint 时遇到问题,并且理
我尝试在下面的代码中添加 foreach 或 for 循环,以便为 Charts.js 创建多个数据集。这将允许我在此折线图上创建多条线。 我有一个 PHP 对象,我可以对其进行编码以稍后填充变量,但
我是一名优秀的程序员,十分优秀!