Передача данных между потоками.

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

krukovis84
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 108
Зарегистрирован: 04.08.2009 (Вт) 11:16
Откуда: Кочевник

Передача данных между потоками.

Сообщение krukovis84 » 04.07.2010 (Вс) 17:35

Всем привет.

Информацию про потоки гуглил - туда не посылайте пожалуйста. Там все для программистов написано, а я колхозник, мне тяжело...
Объясните пожалуйста по человечески, желательно на простом примере как данные полученные в процессе вычисления в фоновом потоке отображать на форме.
Например запустили некий сканер в бесконечном цикле. Есть изначальная форма с кнопкой старт/стоп, на которой есть набор лейблов для отображения данных со сканера.
Как данные сканера присвоить значениям лейблов?

Умоляю! Дайте плиз простой пример (в идеале на лейблах, про тривью я начитался уже, только больше запутался)

Dmitriy2003
Постоялец
Постоялец
 
Сообщения: 690
Зарегистрирован: 27.05.2003 (Вт) 22:47
Откуда: Deutschland

Re: Передача данных между потоками.

Сообщение Dmitriy2003 » 04.07.2010 (Вс) 18:04

krukovis84 писал(а):Дайте плиз простой пример
Простые примеры

krukovis84
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 108
Зарегистрирован: 04.08.2009 (Вт) 11:16
Откуда: Кочевник

Re: Передача данных между потоками.

Сообщение krukovis84 » 04.07.2010 (Вс) 18:36

Dmitriy2003 писал(а):
krukovis84 писал(а):Дайте плиз простой пример
Простые примеры

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

А я хочу понять как между потоками (основным в котором форма моя и фоновым в котором вычисления идут) данные передавать.
Можете подсказать?

krukovis84
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 108
Зарегистрирован: 04.08.2009 (Вт) 11:16
Откуда: Кочевник

Re: Передача данных между потоками.

Сообщение krukovis84 » 04.07.2010 (Вс) 18:45

Добавлю для тех кто возможно будет искать по форуму и наткнется на эту тему.

Примеры там на C# с плохим пояснением. Лучше уже тут почитать : http://www.interface.ru/microsoft/mpnet.htm


Вопрос все еще в силе.

Dmitriy2003
Постоялец
Постоялец
 
Сообщения: 690
Зарегистрирован: 27.05.2003 (Вт) 22:47
Откуда: Deutschland

Re: Передача данных между потоками.

Сообщение Dmitriy2003 » 04.07.2010 (Вс) 18:53

krukovis84 писал(а):Примеры там на C# с плохим пояснением.

:lol:

1Steps
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 505
Зарегистрирован: 20.12.2006 (Ср) 0:50
Откуда: New York

Re: Передача данных между потоками.

Сообщение 1Steps » 04.07.2010 (Вс) 20:54

Это самый простой пример.

Код: Выделить всё
Imports System.Threading

Public Class Form1

    Private _bgThread As Thread
    Private _invokeThread As Thread
    Private _exit As Boolean
    Private _count As Integer

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        _exit = True
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        _bgThread = New Thread(AddressOf Me.DoBackGroundWork)
    End Sub

    Private Sub DoBackGroundWork()
        Do While Not _exit
            Thread.Sleep(New Random().Next(100, 1000))
            _count += 1
            _invokeThread = New Thread(AddressOf Me.InvokeAction)
            _invokeThread.Start()
        Loop
    End Sub

    Private Sub InvokeAction()
        If Me.InvokeRequired Then
            Me.Invoke(New MethodInvoker(AddressOf Me.UpdateLabel))
        End If
    End Sub

    Private Sub UpdateLabel()
        Me.Label1.Text = _count.ToString
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        _bgThread.Start()
    End Sub
End Class
Удалена за ненадобностью.

krukovis84
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 108
Зарегистрирован: 04.08.2009 (Вт) 11:16
Откуда: Кочевник

Re: Передача данных между потоками.

Сообщение krukovis84 » 04.07.2010 (Вс) 21:24

МЕГА СПАСИБО!!!

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

Еще раз Спасибо, всегда выручаете. Архиблагодарен!

1Steps
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 505
Зарегистрирован: 20.12.2006 (Ср) 0:50
Откуда: New York

Re: Передача данных между потоками.

Сообщение 1Steps » 04.07.2010 (Вс) 21:38

МЕГА СПАСИБО!!!
Не спеши особо, не всё так просто как ты думаешь.
Только в этом коде ещё раз пять на грабли наступишь.
Удалена за ненадобностью.

krukovis84
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 108
Зарегистрирован: 04.08.2009 (Вт) 11:16
Откуда: Кочевник

Re: Передача данных между потоками.

Сообщение krukovis84 » 04.07.2010 (Вс) 22:46

У меня не работало, потому что у меня в отдельном модуле все процедуры, а на форме только запуск фонового потока.
А нужно чтобы все процедуры были в одном классе - классе формы.... видимо :cyclops:
Я не знаю почему так...
Я так решил, потому что код выше работает, а если разнести процедуры на 2 модуля. То код перестает работать.
Если кто то сможет объяснить - буду благодарен.

З.Ы. Потоки - Зло... : "Я спросил аудиторию, состоящую из опытных VB-программистов, хотя ли они получить свободную многопоточность будущей версии VB. Практически все подняли руки. Затем я спросил, кто знает, на что он идет при этом. На этот раз руки подняли всего несколько человек, и на их лицах были понимающие улыбки" цитата из Дан Эпплман. Переход на VB.NET: стратегии, концепции.

З.Ы.Ы. Они блин улыбаются там... Представляю сколько они потом слез пролили после того как получили что хотели....

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Передача данных между потоками.

Сообщение FireFenix » 04.07.2010 (Вс) 23:32

krukovis84 писал(а):Я так решил, потому что код выше работает, а если разнести процедуры на 2 модуля. То код перестает работать.
Если кто то сможет объяснить - буду благодарен.

Код в студию... по кофейной гуще баги не выводим :D

upd: почищено для сокращения топика
Последний раз редактировалось FireFenix 05.07.2010 (Пн) 19:25, всего редактировалось 1 раз.
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

krukovis84
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 108
Зарегистрирован: 04.08.2009 (Вт) 11:16
Откуда: Кочевник

Re: Передача данных между потоками.

Сообщение krukovis84 » 05.07.2010 (Пн) 18:35

Код в студию... по кофейной гуще баги не выводим


Ну вот и код. У меня примерно так же было до тех пор пока я в класс формы код из модуля не перенес.

Код: Выделить всё
Imports System.Threading

Public Class Form1

    Public _bgThread As Thread

    Public Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        _exit = True
    End Sub
    Public Sub InvokeAction()
        If Me.InvokeRequired Then
            Me.Invoke(New MethodInvoker(AddressOf Me.UpdateLabel))
        End If
    End Sub

    Public Sub UpdateLabel()
        Me.Label1.Text = _count.ToString
    End Sub

    Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        _bgThread = New Thread(AddressOf DoBackGroundWork)
        _bgThread.Start()
    End Sub
End Class


Код: Выделить всё
Imports System.Threading
Module Module1
    Public _count As Integer
    Public _invokeThread As Thread
    Public _exit As Boolean
    Public Sub DoBackGroundWork()
        Do While Not _exit
            Thread.Sleep(New Random().Next(100, 1000))
            _count += 1
            _invokeThread = New Thread(AddressOf Form1.InvokeAction)
            _invokeThread.Start()
        Loop
    End Sub

End Module


Феникс, передача данных обратно на форму (читай в Главный поток) это не передача данных в консоль как в твоем примере. Данные при передаче в консоль передаются в своем же потоке. Корректно передавать данные между потоками можно только через метод Invoke (это MSDN так утверждает). Как мне кажется - способ что привел 1Steps это единственно возможный вариант отображения данных на форме. Это я так решил, потому что два дня сидел с потоками бился и пока по примеру 1Steps не сделал ничего не работало. Ну и приведенный выше пример, как вы можете убедиться, так же не фурычит. Может нужно еще какие то дополнительные обряды над ним провести чтобы заработал, я не знаю, у меня на это пока понималки не хватает.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Передача данных между потоками.

Сообщение FireFenix » 05.07.2010 (Пн) 19:18

Феникс, передача данных обратно на форму (читай в Главный поток) это не передача данных в консоль как в твоем примере

Ну ты же не сказал, что у тебя именно не получилось с модулями... я подумал - просто вызов из модуля :D

_invokeThread = New Thread(AddressOf Form1.InvokeAction)
_invokeThread.Start()

как бы не прально
Invoke ставит в очередь сообщений, т.е. не нужно создавать новый поток => инвокать нужно существующий объект, а не описание класса
Ну InvokeRequired проверять не обязательно, т.к. можно сам инвок делать из потока, а в форме - обычна функа с присвоением

Код: Выделить всё
Imports System.Threading

Public Class Form1
    Public Options As New Options With {.Doing = True}
    Public Thread As New Thread(AddressOf Module1.Thread)

    Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Thread.Start()
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Thread.Abort()
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Module1.Form1 = Me
    End Sub

    Public Delegate Sub LabelUpdateDelegate(ByVal Value As String)
    Public Sub LabelUpdate(ByVal Value As String)
        Label1.Text = Value
    End Sub
End Class

Public Class Options
    Public Doing As Boolean
End Class

Код: Выделить всё
Imports System.Threading

Module Module1
    Public Form1 As Form1

    Public Sub Thread()
        Dim Count As Integer = 0

        While True
            SyncLock Form1.Options
                If Form1.Options.Doing = False Then Exit While
            End SyncLock

            System.Threading.Thread.Sleep(500)

            Count += 1

            Form1.Invoke(New Form1.LabelUpdateDelegate(AddressOf Form1.LabelUpdate), Count.ToString)
        End While
    End Sub
End Module

Ня

И кстати шара инвока в том, что также можно без извращений передавать вагон параметров в основной поток :) А в новый поток (Thread) только через костыль
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

krukovis84
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 108
Зарегистрирован: 04.08.2009 (Вт) 11:16
Откуда: Кочевник

Re: Передача данных между потоками.

Сообщение krukovis84 » 05.07.2010 (Пн) 21:12

Спасибо! Буду разбираться... :study:


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4

    TopList