【问题标题】:I need help creating a TaskScheduler to prevent threading overload我需要帮助创建一个 TaskScheduler 以防止线程过载
【发布时间】:2016-05-06 22:41:22
【问题描述】:

我想将工作人员添加到队列中,但只有前 N 个工作人员并行处理。我找到的所有示例都在 C# 中。

这对程序员来说可能很简单,但我不是。我对 VB 的了解足以编写简单的程序。

但是我的第一个应用程序运行良好,直到它突然达到 100% CPU 然后崩溃。请帮忙(是的,我已经浪费了 5 个小时的工作时间搜索才发布此内容......)

更多上下文:对具有超过 100 万个目录/子目录的文件服务器执行目录结构、文件和权限的递归清单。

流程连续运行,但需要数月才能完成。管理层已经在我的脖子上呼吸了。当我尝试使用 Tasks 时,它会进入大约 1000 个线程,然后达到 100% CPU,停止响应,然后崩溃。这是在具有 112 GB RAM 的 16 核服务器上。

--添加 因此,通过使用信号量提供的示例,这就是我放入的内容:

Public Class InvDir
    Private mSm as Semaphore
    Public Sub New(ByVal maxPrc As Integer)
        mSm = New Semaphore(maxPrc, maxPrc)
    End Sub

    Public Sub GetInventory(ByVal Path As String, ByRef Totals As Object, ByRef MyData As Object)
        mSm.WaitOne()

        Task.Factory.StartNew(Sub()
                Dim CurDir As New IO.DirectoryInfo(Path)
                Totals.SubDirectoryCount += CurDir.GetDirectories().Count
                Totals.FilesCount += CurDir.GetFiles().Count
                For Each CurFile As IO.FileInfo in CurDir.EnumerateFiles()
                    MyData.AddFile(CurFile.FileName, CurFile.Extension, CurFile.FullName, CurFile.Length)
                Next
                End Sub).ContinueWith(Function(x) mSm.Release())
    End Sub
End Class

【问题讨论】:

  • 告诉“管理层”聘请顾问。
  • 您的问题范围太广,我们无法解释为什么我们看不到的代码行为不正常。我们不会为您编写任务调度程序,也不是可以教您这样做的教程网站。如果您对 VB 有足够的了解以编写简单的程序,那么您的要求超出了您当前的技能,您需要告诉管理层您需要帮助,以便他们可以聘请承包商或程序员。
  • 我不是要别人写一个“任务调度器”。 .NET 中有一个 TaskScheduler OBJECT,我找到的关于如何使用它的所有示例代码都在 C# 中。我只是问如何在 VB.NET 中做到这一点。我把我正在做的事情放在上下文中,而不是要求有人为我做我的工作。我尝试过使用 Task 对象的 Collection 和 Parallel.ForEach 方法,但它们很快就会占用所有线程。
  • 我建议将您现有的代码添加到您的问题中。在 cmets 中几乎不可读。
  • 您已经尝试过 Tasks 和 Parallel.ForEach,您正在编写递归函数,并且正如您所提到的,您只是在寻找提供输入的人,而不是为您完成工作。谁告诉你你不是程序员?

标签: vb.net multithreading task taskscheduler


【解决方案1】:

您正在尝试使用磁盘 I/O 进行多线程处理。它可能会变得越来越慢因为你正在向它抛出更多线程。无论有多少线程,磁盘在物理上一次只能查找一个位置。 (事实上​​,你提到它是串行工作的。)

如果您确实想限制并发线程的数量,您可以使用Semaphore。信号量类似于同步锁,只是您可以指定一次允许多少个线程执行代码。在下面的示例中,信号量允许三个线程执行。除此之外,必须等到一个完成。来自 MSDN 页面的一些修改代码:

Public Class Example

    ' A semaphore that simulates a limited resource pool.
    '
    Private Shared _pool As Semaphore

    <MTAThread> _
    Public Shared Sub Main()
        ' Create a semaphore that can satisfy up to three
        ' concurrent requests. Use an initial count of zero,
        ' so that the entire semaphore count is initially
        ' owned by the main program thread.
        '
        _pool = New Semaphore(0, 3)          

    End Sub

    Private Sub SomeWorkerMethod()
        'This is the method that would be called using a Task.
        _pool.WaitOne()
        Try
            'Do whatever
        Finally
            _pool.Release()
        End Try
    End Sub
End Class

每个新线程都必须调用_pool.WaitOne()。这告诉它等待轮到它,直到执行的线程少于三个。每个线程都会阻塞,直到信号量允许它通过。

每个线程还必须调用_pool.Release() 让信号量知道它可以允许下一个等待线程开始。这很重要,即使有例外。如果线程不调用Release(),那么信号量将永远阻塞它们。

如果真的需要五个月的时间,那么克隆驱动器并对同一驱动器的多个实例运行检查,每个实例查看不同的部分呢?

【讨论】:

  • 谢谢。这很有帮助。我还发现 TaskScheduler 在 ThreadPool 内部。它可以通过使用 ThreadPool.SetMaxthreads() 来限制。
  • 这可能是一个更好的解决方案。他们在处理信号量等晦涩的事物方面做得更好,并提供了更简单、更直观的方式来做同样的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-20
  • 1970-01-01
  • 2022-01-13
相关资源
最近更新 更多