2013-07-15 3 views
0

Я пытаюсь создать многопоточную программу для опроса компьютеров для данных, но я не могу заставить ее работать правильно. Код ниже работает и создает 4 потока, как и следовало ожидать, но поток кода, похоже, происходит последовательно и по основному потоку пользовательского интерфейса.Многопоточность Vb.net не работает ...?

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

Ниже приведена своя версия того, что у меня есть, но она служит для демонстрации проблемы. Для информации «testclass» - это класс, используемый как экземпляр машины с каждым элементом класса, представляющим свойство машины.

Надеюсь, что я дал достаточно информации, чтобы объяснить проблему. Заранее спасибо.

Пс Мне не нужно обновлять форму, если я?

Imports System.Threading 

Public Class TestForm 

Public threadcount As Integer 
Public Delegate Sub testclassDelegate(test As Object) 

Private Class testclass 
    Public index As Integer 
    Public TestVal1 As Integer = 100 
    Public TestVal2 As Integer = 200 
    Public TestVal3 As Integer = 300 
    Public TestVal4 As Integer = 400 
    Public TestVal5 As Integer = 500 
    Public TestVal6 As Integer = 600 
    Public testDel As testclassDelegate 
End Class 

Private Sub TestForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load 
    For i As Integer = 0 To 3 
     DataGridView1.Rows.Add() 
     DataGridView1.Rows(i).Cells(0).Value = i + 1 
    Next 
End Sub 

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
    For i As Integer = 0 To 3 
     DataGridView1.Rows(i).Cells(1).Value = "" 
     DataGridView1.Rows(i).Cells(2).Value = "" 
     DataGridView1.Rows(i).Cells(3).Value = "" 
     DataGridView1.Rows(i).Cells(4).Value = "" 
     DataGridView1.Rows(i).Cells(5).Value = "" 
     DataGridView1.Rows(i).Cells(6).Value = "" 
    Next 
    Poll_FreeThread() 
End Sub 

Private Sub Poll_FreeThread() 
    For i As Integer = 0 To DataGridView1.Rows.Count - 1 
     Dim test As New testclass 
     test.index = i 
     test.testDel = AddressOf UIUpdate 

     Interlocked.Increment(threadcount) 
     Me.Label2.Text = threadcount 
     Try 
      Dim thPoll As New Thread(Sub() invokeUIUpdate(test)) 
      thPoll.IsBackground = True 
      thPoll.Priority = ThreadPriority.BelowNormal 
      thPoll.Start() 
     Catch ex As Exception 
      MsgBox(ex.Message) 
     End Try 
    Next 
End Sub 

Public Sub invokeUIUpdate(test As Object) 
    If DataGridView1.InvokeRequired Then 
     DataGridView1.Invoke(New testclassDelegate(AddressOf UIUpdate), test) 
    Else 
     UIUpdate(test) 
    End If 
End Sub 

Public Sub UIUpdate(test As Object) 
    Thread.Sleep(test.index * 100) 
    DataGridView1.Rows(test.index).Cells(1).Value = test.TestVal1 
    Me.Refresh() 
    Thread.Sleep(100) 
    DataGridView1.Rows(test.index).Cells(2).Value = test.TestVal2 
    Me.Refresh() 
    Thread.Sleep(100) 
    DataGridView1.Rows(test.index).Cells(3).Value = test.TestVal3 
    Me.Refresh() 
    Thread.Sleep(100) 
    DataGridView1.Rows(test.index).Cells(4).Value = test.TestVal4 
    Me.Refresh() 
    Thread.Sleep(100) 
    DataGridView1.Rows(test.index).Cells(5).Value = test.TestVal5 
    Me.Refresh() 
    Thread.Sleep(100) 
    DataGridView1.Rows(test.index).Cells(6).Value = test.TestVal6 
    Me.Refresh() 
    Interlocked.Decrement(threadcount) 
    Me.Label2.Text = threadcount 
End Sub 

End Class 
+0

Подсказка: Установить точку останова на 'invokeUIUpdate' и посмотреть, что произойдет с' if'. –

+0

1. Вы проверили с _Me.InvokeRequired_ вместо _DataGridView1.InvokeRequired_? 2. Кроме того, нет необходимости вызывать _Me.Refresh() _ после установки каждого значения ячейки, вы можете поместить его только один раз после установки последнего значения ячейки. – Coder

+0

Спасибо Раймонду. Это перешло мне в голову, но, увы, это не работало иначе, если это то, что вы имели в виду? – doovers

ответ

1

запустить свой код немного по-другому, это как структура должна выглядеть для многопоточности в vb.net (это что-то делать с Vb.net не проходит Пространства имен в модели от того, что я понимаю)

Это будет ваш startThread от MainThread нагрузки или ж/д у вас

Private Sub DoSomethingSimple() 
    Dim DoSomethingSimple_Thread As New Thread(AddressOf DoSimple) 
    DoSomethingSimple_Thread.Priority = ThreadPriority.AboveNormal 
    DoSomethingSimple_Thread.Start(Me) 
End Sub 

Это будет фактическая нить Сама (новая модель/класс или в одном классе)

Private Sub DoSimple(beginform As Form) 
    'Do whatever you are doing that has nothing to do with ui 

    'For UI calls use the following 
    SomethingInvoked(PassibleVariable, beginform) 

End Sub 

Написать метод делегата и Invoke для каждого вызова в основной поток.

Delegate Sub SomethingInvoked_Delegate(s As Integer, beginform As Form) 
Sub SomethingInvoked_Invoke(ByVal s As Integer, beginform As Form) 
    If beginform.NameOfControlYouAreUpdating.InvokeRequired Then ' change NameOfControlYouAreUpdating to the Name of Control on the form you wish to update 
     Dim d As New SomethingInvoked_Delegate(AddressOf SomethingInvoked_Invoke) 
     beginform.Invoke(d, New Object() {s, beginform}) 
    Else 

     'Do something... 
     beginform.NameOfControlYouAreUpdating.Condition = Parameter 

    End If 
End Sub 

Это проверено (не висит) способ написания Threads в vb.net

Если вам нужна дополнительная помощь реализации кода для этого шаблона, дайте мне знать: P

+0

Спасибо, что он работает с модификацией вашего кода! – doovers

-1

Вы можете использовать таймер и BackgroundWorker с случае DoWorkEventHandler и RunWorkerCompletedEventHandler.

Пример: C# пример:

private void Button1_Click(object sender, EventArgs e) 
{ 
workerThreadForLetters.WorkerReportsProgress = true;     workerThreadForLetters.WorkerSupportsCancellation = true; 
workerThreadForLetters.DoWork -= new DoWorkEventHandler(workerThreadForLetters_DoWork); 
workerThreadForLetters.DoWork += new DoWorkEventHandler(workerThreadForLetters_DoWork); 

workerThreadForLetters.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(workerThreadForLetters_RunWorkerCompleted); 

workerThreadForLetters.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workerThreadForLetters_RunWorkerCompleted); 
} 
    private void workerThreadForLetters_DoWork(object sender, DoWorkEventArgs e) 
    { 
       //DO SOMETHING 
    } 
    private void workerThreadForLetters_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
      //DO AS REQUIRED 
      Timer1.enable = false; 
    } 
    private void tmCollectionLettersUpdate_Tick(object sender, EventArgs e) 
    { 
      //Content update like % of data progressed or any. 
    } 
+0

Благодарим вас за предложение и оправдаем мое невежество, но разве я не ограничиваюсь одним работником фона?В конечном счете, я буду опросить до 100 машин одновременно в непрерывном цикле, поэтому я не уверен, что bgworker будет работать в этом случае ?? – doovers

+0

Вы можете запустить столько фоновых работ, сколько хотите, но это нехорошее решение. Я думаю, что threadpool может быть более подходящим. Это теоретические знания, поэтому я не предоставляю код - извините. Но вы должны использовать только несколько потоков, в зависимости от потребления ресурсов ваших потоков. –

+0

Привет, христианин. Я действительно закодировал два варианта в своем решении: один использовал threadpool и один использовал неограниченные потоки для тестирования позже со многими машинами, чтобы увидеть, как далеко я могу нажать. Моя проблема заключается в том, что при опросе компьютеров требуется быстрый поворот, но программа будет работать непрерывно на выделенной машине, поэтому я бы предположил, что было бы хорошо нажать ее, поскольку никаких других требований этой машины не будет. Для меня это все новая территория, поэтому я открыт для любых советов! – doovers

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