2016-05-06 5 views
0

Я хочу добавить работников в очередь, но только первые N рабочих обрабатывают параллельно. Все образцы, которые я нахожу, находятся на C#.Мне нужна помощь в создании TaskScheduler для предотвращения перегрузки потоком

Это, наверное, просто для программиста, но я не один. Я достаточно знаю о VB, чтобы писать простые программы.

Но мое первое приложение работает нормально, пока оно внезапно не достигнет 100% -ного CPU, а затем сработает. Помогите, пожалуйста (да, я потратил 5 часов на поиск рабочего времени, прежде чем публиковать это ...)

Подробнее Контекст: Выполнение рекурсивного инвентаризации структур каталогов, файлов и разрешений на файловых серверах с более чем 1 миллионом каталогов/подкаталогов.

Процесс работает серийно, но для его завершения потребуется несколько месяцев. Менеджмент уже дышит мне на шею. Когда я пытаюсь использовать Tasks, он переходит к примерно 1000 потокам, затем обращается к 100% процессору, перестает отвечать на запросы, а затем падает. Это на 16-ядерном сервере с 112 ГБ оперативной памяти.

--Added Таким образом, с образцом, представленной на использовании семафоров, это то, что я поместил в:

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 
+1

Сообщите «Менеджменту», чтобы нанять консультанта. – Plutonix

+0

Ваш вопрос слишком широк по объему, и мы не можем объяснить, почему код, который мы не видим, не ведет себя правильно. Мы не собираемся писать планировщик задач для вас, и мы не являемся учебным сайтом, где мы можем научить вас делать это. Если вы * достаточно знаете о VB для написания простых программ *, то, что вы спрашиваете, выше вашего текущего набора навыков, и вам нужно сообщить руководству, что вам нужна помощь, чтобы они могли нанять подрядчика или программиста. –

+0

Я не прошу кого-нибудь написать «планировщик задач». В .NET есть объект TaskScheduler OBJECT и весь пример кода, который я нахожу, как использовать его на C#. Я только спрашивал, как это сделать в VB.NET. Я вложил то, что я делаю, чтобы дать контекст, не прося кого-то сделать для меня свою работу. Я попытался использовать объекты Collection of Task и методы Parallel.ForEach, но вскоре они заняли все потоки. – HelpThisisNOTmyJob

ответ

1

Вы пытаетесь многопоточности с диска ввода/вывода. Это может быть медленнее , потому что вы бросаете в него больше потоков. Независимо от того, сколько потоков существует, диск может физически искать только одну позицию за раз. (Фактически вы упомянули, что он работает серийно.)

Если вы хотите ограничить количество одновременных потоков, вы можете использовать Semaphore. Семафор подобен syncLock, за исключением того, что вы можете указать, сколько потоков разрешено выполнять код за раз. В приведенном ниже примере семафор позволяет выполнять три потока. Больше, чем нужно, дождаться завершения. Некоторые модифицированный код страницы 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(), тогда семафор просто блокирует их навсегда.

Если на самом деле это займет пять месяцев, а как же клонировать диск и запустить проверку на нескольких экземплярах одного диска, каждый из которых смотрит на разные разделы?

+0

Спасибо. Это полезно. Я также обнаружил, что TaskScheduler является внутренним для ThreadPool. Его можно ограничить, используя ThreadPool.SetMaxthreads(). – HelpThisisNOTmyJob

+0

Это, вероятно, лучшее решение. Они стали лучше принимать неясные вещи, такие как семафор, и предлагать более простые, более интуитивные способы сделать то же самое. –

Смежные вопросы