Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 |

 

  Вопрос: Нужна помощь с многопоточностью. Добавлено: 22.11.10 11:44  

Автор вопроса:  Oleg
Имеется программа. Которая (как я планировал) должна считать от 1 до .. значения заданного пользователем. Выполняться это должно в количестве потоков заданных пользователям. Результат записывается в ListBox в формате:

[номер потока] : [число]
[визуальный разделитель между потоками вида "======"]

На данный момент программа работает не корректно, а именно делает следующий вывод:

(При количестве потоков - 3, при счете от 1 до 9)

0 : 1
0 : 2
0 : 3
0 : 4
0 : 5
0 : 6
0 : 7
0 : 8
0 : 9
=============
1 : 1
1 : 2
1 : 3
1 : 4
1 : 5
1 : 6
1 : 7
1 : 8
1 : 9
=============
2 : 1
2 : 2
2 : 3
2 : 4
2 : 5
2 : 6
2 : 7
2 : 8
2 : 9

Как мне добиться корректного вывода? Выглядеть он должен так:

0 : 1
=========
1 : 2
=========
2 : 3
=========
0 : 4
=========
1 : 5
=========
2 : 6
=========
0 : 7
=========
1 : 8
=========
2 : 9

--------
Вот исходник (так же для удобочитаемости можете скачать его тут (Visual Studio 2010, с коментами на инглиш) - http://rapidshare.com/files/432386064/Threads.zip):


Imports System.Threading

Public Class Form1

    Private Delegate Sub addToListBox_d(ByVal result As String)
    Private threadCounters As New List(Of Integer)()
    Private maxCount As Integer
    Private threadLock As New Object

    Private Sub addToListBox(ByVal result As String)
        If Me.InvokeRequired() Then
            Me.Invoke(New addToListBox_d(AddressOf addToListBox), New Object() {result})
        Else
            ListBox1.Items.Add(result)
        End If
    End Sub

    Private Sub DoWork(ByVal state As Object)
        Monitor.Enter(threadLock)
        Try
            Dim threadIndex As Integer = Integer.Parse(Thread.CurrentThread.Name)
            Dim count As Integer = threadCounters(threadIndex)
            For loopCount As Integer = 1 To maxCount
                addToListBox(Thread.CurrentThread.Name + " : " + loopCount.ToString())
            Next
            addToListBox("==========")
        Finally
            Monitor.Exit(threadLock)
        End Try
    End Sub

    Private Sub StartButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartButton.Click

        Dim counter As Integer = 0
        Dim threadCount As Integer = Integer.Parse(cboNoOfThreads.Text)

        If Integer.TryParse(txtMaxCount.Text, maxCount) Then
            Do While (counter < threadCount)
                Dim t As Thread = New Thread(AddressOf DoWork)
                t.IsBackground = True
                t.Name = counter.ToString()
                threadCounters.Add(0)
                t.Start(counter)
                counter += 1
            Loop
        End If

    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        cboNoOfThreads.SelectedIndex = 0
    End Sub

End Class

Ответить

  Ответы Всего ответов: 15  

Номер ответа: 1
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #1 Добавлено: 22.11.10 12:37
На данный момент программа работает не корректно

как раз таки она работает корректно согласно тому коду,что ты написал..
поскольку ты используешь блокировки,то следующий поток НЕ может запуститься, пока не завершит работу предыдущий..
чтобы все зарабоатло так как тебе нужно закомментируй строки:

Ответить

Номер ответа: 2
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #2 Добавлено: 22.11.10 12:38
Monitor.Enter(threadLock)
 Monitor.Exit(threadLock)

в данном случае они не нужны..

Ответить

Номер ответа: 3
Автор ответа:
 Oleg



Вопросов: 1
Ответов: 3
 Профиль | | #3 Добавлено: 22.11.10 13:59
Ситуация действительно проясняется. Но с выводом не получается.
--Текущий результат--
0 : 0
1 : 0
2 : 0
0 : 1
1 : 1
2 : 1
0 : 2
1 : 2
2 : 2
...
--------

Ответить

Номер ответа: 4
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #4 Добавлено: 22.11.10 14:15
0 : 0
1 : 0
2 : 0

В данном случае потоки работают независимо друг от друга.. и каждый считает свою переменную. Это их типичное поведение.
Чтоб не мутить воду попытайся объяснить задачу.. ЧТО ты пытаешься сделать.. Потому как твое желание заставить работать потоки следующим образом:
0 : 1
=========
1 : 2
=========
2 : 3

мягко говоря вызывает недоумение.. Либо ты не понимаешь сути потоков и задачи которые они выполняют, либо твоя задача достаточно не тривиальная и требует использование механизмов синхронизации потоков.

Ответить

Номер ответа: 5
Автор ответа:
 Oleg



Вопросов: 1
Ответов: 3
 Профиль | | #5 Добавлено: 22.11.10 14:29
Вообще эта программа для экспериментов над потоками. А целевой софт должен будет выполнять web запросы в многопоточном режиме.

К примеру софт по загрузке новостей:

http://site.com/news/?page=1

.....

до http://site.com/news/?page=3000

Тоесть требуется чтобы каждый поток выполнял свой запрос.

К примеру заданно 5 потоков:

0 - http://site.com/news/?page=1
1 - http://site.com/news/?page=2
2 - http://site.com/news/?page=3
3 - http://site.com/news/?page=4
4 - http://site.com/news/?page=5
после загруки этих страниц нужно чтобы потоки продолжали в том же духе до page=3000.
0 - http://site.com/news/?page=6
1 - http://site.com/news/?page=7
2 - http://site.com/news/?page=8
3 - http://site.com/news/?page=9
4 - http://site.com/news/?page=10
.....

У меня в программировании 2 проблемы - регулярки и многопоточность )) Трудно въехать без хорошего примера.

Ответить

Номер ответа: 6
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #6 Добавлено: 22.11.10 14:51
ну как я и думал.. стандартная задача не требующая очередности выполнения..
В твоем случае правильнее будет сделать так:
1. Создать очередь
2. Заполнить ее URLами
3. Запустить N-потоков в зависимости от ширины твоего канала.. Потому что если запустить слишком много потоков, они не смогут одновременно выполнить много запросов и будут отваливаться по timeout
Далее в потоке происходит следуещее:
- Блокируешь очередь через Lock (это аналог Monitor.Enter/Exit)
- Проверяешь количестов элементов в очереди, если там есть элементы,то достаешь очередной URL (снимаешь блокировку с очереди,чтоб другие потоки могли работать с нею)
- Выполняешь запрос
- Обрабатываешь полученную страницу (сохраняешь,парсишь и т.д..)
- и так крутишь цикл до тех пор пока очередь не опустеет..

Таким образом 5-10 потоков у тебя будут работать с одной очередью и загрузят все страницы..

Ответить

Номер ответа: 7
Автор ответа:
 Oleg



Вопросов: 1
Ответов: 3
 Профиль | | #7 Добавлено: 22.11.10 15:47
Спасибо, буду пробовать, правда с пулами вообще не знаком.

Ответить

Номер ответа: 8
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #8 Добавлено: 22.11.10 16:06
с пулами тоже ничего сложного.. не разберешься - пиши,объясню..

Ответить

Номер ответа: 9
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #9 Добавлено: 22.11.10 16:22
Пул потоков здесь вообще не нужен.

Если ты пишешь на 4.0, то задача очень приятно решается на классе BlockingCollection. Если на чем-то более старом, то надо мутить со стандартной Queue<T>, которая не является потокобезопасной, и для корректной ее работы в таком сценарии нужно навешивать целую кучу синхронизаций.

Ответить

Номер ответа: 10
Автор ответа:
 AgentFire



ICQ: 192496851 

Вопросов: 75
Ответов: 3178
 Профиль | | #10 Добавлено: 22.11.10 16:36
SynсLock на 3.5 не дает потокобезопасность?

Ответить

Номер ответа: 11
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #11 Добавлено: 22.11.10 17:06
SynсLock на 3.5 не дает потокобезопасность?

дает, если писать прямыми руками..

Ответить

Номер ответа: 12
Автор ответа:
 AgentFire



ICQ: 192496851 

Вопросов: 75
Ответов: 3178
 Профиль | | #12 Добавлено: 22.11.10 23:27
ну дык и зачем тогда все эти ваши мьютексы :)

Ответить

Номер ответа: 13
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #13 Добавлено: 23.11.10 00:52
Зачем все эти ваши SyncLock когда есть BlockingCollection?

Ответить

Номер ответа: 14
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #14 Добавлено: 23.11.10 09:06
BlockingCollection есть только в FW 4.0, и далеко не все его юзают и считают необходимым переходить на него только из за BlockingCollection

Ответить

Номер ответа: 15
Автор ответа:
 mihar



ICQ: Днепропетровск... 

Вопросов: 0
Ответов: 1
 Профиль | | #15 Добавлено: 25.11.10 15:00
del

Ответить

Страница: 1 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам