带有大量sendasync的Vb.net内存问题 [英] Vb.net memory problem with large number of sendasync

查看:90
本文介绍了带有大量sendasync的Vb.net内存问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景,我正在尝试制作网络扫描仪,就像生气的ip扫描仪一样。这主要是出于教育目的,我可以使用angryip =)。问题是我试图使用sendasync与处理程序ping一个范围内的所有IP地址。下面的代码适用于几个地址。如果我尝试更大的东西,例如b类子网(大约64,000个地址),我最终会耗尽内存(或者我达到其他限制)。如果我调试程序,我看到内存使用量达到2GB,然后我得到一个错误。据说.net框架4.5+已经删除了这个限制,但是当我构建4.6时仍然会出现错误。我可能会遇到其他一些限制,它只是与2gb限制一致,但它似乎与内存有关。



值得注意的是,如果我做了少量的测试ips p_pingCompleted子被触发,我收到消息框,说明已解雇但是如果我创建了大量的ping测试,p_pingCompleted子从不触发(没有创建消息框)。似乎我花费所有cpu时间创建处理程序并将ping发送到我从未到达p_pingCompleted子的点。我意识到我可能会把工作量分成更小的部分,但这不是最佳的。每个ping产生一个单独的线程是一个可行的选项(64,000个线程似乎很多=)。还有其他想法吗?我正在使用的代码似乎是一个常见的推荐,从技术上说它确实有效,只是没有达到这个规模。



我尝试过的方法:



Background, I am trying to make a network scanner, much like angry ip scanner. This is mostly for educational purposes, I could just use angryip =). The issue is i am trying to use sendasync with a handler to ping all ip addresses in a range. The code below works with a few addresses. If i try something much larger, such as a class b subnet (approximately 64,000 addresses) I end up running out of memory (or i hit some other limit). If i debug the program i see memory usage hit 2gb and then i get an error. the .net framework 4.5+ supposedly removed this limitation but i still get the error when i build against 4.6. I may be hitting some other limit and it just coincides with the 2gb limit but it seems to be memory related.

Of note, if i do a small number of test ips the p_pingCompleted sub is fired and i receive the message box stating "fired" however if i create a large number of ping tests the p_pingCompleted sub never fires (no message box is created). it seems that i am spending all cpu time creating the handlers and sending the pings to the point i never get to the p_pingCompleted sub. I realize i could probably break the workload into smaller pieces but that is not optimal. Is spawning a seperate thread per ping a viable option (64,000 threads seems like a lot =). Any other thoughts? the code i am using seems to be a common recommendation and technically it does work, just not at this scale.

What I have tried:

Private d As New Dictionary(Of String, Ping)
Private Sub removeInactive(sender As Object, e As EventArgs) Handles Button2.Click
 For Each item As ListViewItem In lv1.Items
 Dim p As New Ping
           d.Add(item.Text, p)
           AddHandler p.PingCompleted, AddressOf p_pingCompleted
                p.SendAsync(item.Text, 20, item)

        Next


    End Sub

    Private Sub p_pingCompleted(ByVal sender As Object, ByVal e As System.Net.NetworkInformation.PingCompletedEventArgs)
        MsgBox("fired")

        Dim p As Ping = DirectCast(sender, Ping)
        Dim lvi As ListViewItem = DirectCast(e.UserState, ListViewItem)
        If e.Reply.Status = IPStatus.Success Then

        Else
            lvi.Remove()

        End If

        RemoveHandler p.PingCompleted, AddressOf p_pingCompleted
        p.Dispose()

        lv1.Refresh()
    End Sub

推荐答案

问题是你已经创建了数千个线程,因为你没有正确控制它。创建的每个线程还为堆栈空间分配1MB内存。如果你能够创建64,000个线程,那么你也将分配64TB的内存。不。展望。要发生这种情况。



更好的方法是创建一个同步执行Ping的小类,然后使用并行foreach执行所有ping操作。这将允许任务管理器使用线程池并一次最多运行8个ping。
The problem is that you've got thousands of threads being created because you're not controlling this properly. Each thread that's created also allocates 1MB of memory for stack space. If you were able to create 64,000 threads, you'd also be allocating 64TB of memory. Not. Going. To Happen.

A better way would be to create a small class that does a Ping synchronously and then use the parallel foreach to do all the pings. This will allow the Task manager to use the thread pool and run up to 8 pings at a time.


这篇关于带有大量sendasync的Vb.net内存问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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