2015-03-12 3 views
0

Фон: У меня есть программа, которая обрабатывает множество записей в базе данных и создает задачи для выполнения. (В этом случае создание учетных записей пользователей в AD). Часть этого заключается в создании пользовательских каталогов, профилей и домашних каталогов и установке разрешений на них. Необходимо подождать, пока учетная запись объявления не будет реплицирована во всех наших DC.Проблемы с Threading в vb.net

Итак, у моей программы будет отдельный поток, ответственный за создание каталогов, которые будут обрабатывать очередь, заполненную из основного потока.

Я сделал некоторые исследования по Threading и придумать следующий шаблон кода:

Imports System.Threading 

Public Class Form1 
Dim worker As Object 
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 
    worker = New workerObj(AddressOf resultcallback) 
    Dim t As New Thread(AddressOf worker.mainloop) 
End Sub 

Public Sub resultcallback(ByVal item As String) 
    Outbox.AppendText(item) 
End Sub 

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
    worker.addItem(inbox.Text) 
End Sub 
End Class 

Public Delegate Sub resultcallback(ByVal item As String) 

Public Class workerObj 
Private myQueue As New Queue(Of String) 
Private myCallback As resultcallback 
Dim item As String = "nout" 

Public Sub New(ByVal callbackdelegate As resultcallback) 
    myCallback = callbackdelegate 
End Sub 

Public Sub mainloop() 
    While True 
     If myQueue.Count > 0 Then 
      item = myQueue.Dequeue() 
      myCallBack(item) 
     End If 
     Thread.Sleep(5000) 
    End While 
End Sub 

Public Sub addItem(ByVal item As String) 
    myQueue.Enqueue(item) 
End Sub 
End Class 

Проблема: На линии Dim т как новую нить .....

Error 1 Overload resolution failed because no accessible 'New' is most specific for these arguments: 
'Public Sub New(start As System.Threading.ParameterizedThreadStart)': Not most specific. 
'Public Sub New(start As System.Threading.ThreadStart)': Not most specific. n:\visual studio 2013\Projects\ThreadTest\ThreadTest\Form1.vb 7 13 ThreadTest 

Может ли кто-нибудь помочь мне сказать, где я ошибся? Cheers.

+0

вопрос не имеет ничего общего с многопоточности. Перед написанием кода вы должны проверить документацию метода, который вы пытаетесь использовать, и обеспечить его компиляцию. Более того, я предлагаю вам использовать задачи вместо необработанных потоков, поскольку они упрощают параллельное программирование, и они помогают избежать многих проблем с использованием потоков. Например, создание потока дорого, поэтому его следует избегать в пользу использования потоков ThreadPool. Task.Run делает это под обложками –

ответ

1

Темы не имеют общего конструктора, вам нужно вызвать Thread.Start. Я бы предложил, чтобы вы этого не делали. Написание потокобезопасного кода достаточно сложно, когда вы знаете о многопоточном программировании.

Например, в вашем коде вы изменяете очередь из двух разных потоков без блокировки. Очередь не является потокобезопасной, и вы можете повредить очередь. Вы должны заблокировать доступ к нему или использовать ConcurrentQueue, который равен поточно-безопасный. Другая ошибка заключается в попытке изменить TextBox из другого потока - это приведет к исключению, потому что только пользовательский интерфейс разрешает изменять элементы пользовательского интерфейса.

Лучшим вариантом является использование класса ActionBlock из библиотеки DataFlow, которая уже выполняет то, что вы хотите: запросы очереди и обрабатываете их в одном или нескольких отдельных потоках.

Ваш код может быть столь же простым, как это:

Dim myFileWorker=New ActionBlock(Of string)(Function(path) =>DoSomething(path)) 

For Each somePath As String in ListWithManyPaths 
    myFileWorker.Post(somePath) 
Next somePath 

myFileWorker.Complete() 
myFileWorker.Completion.Wait() 

По умолчанию один путь будет обрабатываться только на время. Чтобы обработать несколько путей вы передаете ExecutionDataflowBlockOptions объект с требуемым MaxDegreeOfParallelism:

Dim options=New ExecutionDataflowBlockOptions() With { .MaxDegreeOfParallelism=5} 
Dim myFileWorker=New ActionBlock(Of String) Function(path) DoSomething(path),options)  
+0

Обратный вызов предназначен для передачи данных обратно в основной поток (ui) для обновления текстового поля. Итак, с помощью ActionBlock, как бы я мог называть mainlop sub для чтения объекта conncurentqueue? – Peterp

+0

Или мне не нужна очередь? Это будет генерировать тысячи учетных записей, поэтому я не хочу генерировать тысячи потоков (отсюда и моя идея использовать какую-то очередь, с двумя потоками управления. Один из них производит данные, а один из них - – Peterp

+0

. входящие сообщения, поэтому вам не нужно ничего стоять в очереди. Управление количеством потоков так же просто, как установка MaxDegreeOfParallelism = 2. Для обновления пользовательского интерфейса вы либо используете обратный вызов и вызов, либо используете [Прогресс (Of T)] (https : //msdn.microsoft.com/en-us/library/hh193692%28v=vs.110%29.aspx) в .NET 4.5 для отправки сообщений из нескольких потоков в поток пользовательского интерфейса.Это позволяет использовать сложные события прогресса, ставить в очередь несколько событий, не блокируя рабочих, и отделяет рабочих от фактического метода/обратного вызова, который делает отчетность. –