Форум программистов, компьютерный форум, киберфорум
Visual Basic .NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.89/18: Рейтинг темы: голосов - 18, средняя оценка - 4.89
0 / 0 / 0
Регистрация: 25.06.2013
Сообщений: 112
1

Передать данные из основного потока в дочерний

28.09.2017, 13:20. Показов 3266. Ответов 18
Метки нет (Все метки)

Здравствуйте,
у меня есть программа с основным кодом, который крутиться в бесконечном цикле и опрашивает внешнее устройство. Проект windows form, но запускается с главной функции, т.е. работает вне формы. Теперь есть задача вывести лог в отдельное окно, однако так как программа работает в основном цикле форма созданная в проекте тормозит. Я хотел бы создать форму в отдельном потоке и передавать ей данные. Как это реализовать? Я смог нагуглить только передачу данных из дочернего потока в основной.
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.09.2017, 13:20
Ответы с готовыми решениями:

Передать данные из родительского виджета в дочерний и обратно
Доброго времени суток! Столкнулся с проблемой и не могу решить уже около двух дней. Сейчас...

Выполнение слота основного потока через сигнал второстепенного потока
Доброго времени суток! Вопрос следующий. В основном потоке создается кнопка и Qlabel class...

Из потока в форму передать данные
Так ситуация. Есть form1 на которой есть listbox1. есть поток по имени rec. поток работает...

Как передать данные из одного потока в другой?
Есть отдельный поток для чтения данных и основной поток для обработки данных. Из этого потока...

18
Администратор
Эксперт .NET
13851 / 11225 / 4569
Регистрация: 17.03.2014
Сообщений: 22,616
Записей в блоге: 1
28.09.2017, 13:25 2
Anforcer, логичнее сделать наборот - вынести существующий код в отдельный поток и из него обновлять форму. Передачу данных в окно можно с помощью метода Control.Invoke().
0
0 / 0 / 0
Регистрация: 25.06.2013
Сообщений: 112
29.09.2017, 12:34  [ТС] 3
Сейчас основной код уже разросся и с ним связано много функций. Правильно ли я понимаю, что так не получится?
0
Администратор
Эксперт .NET
13851 / 11225 / 4569
Регистрация: 17.03.2014
Сообщений: 22,616
Записей в блоге: 1
29.09.2017, 13:37 4
Anforcer, на этот вопрос невозможно дать ответ не изучив код приложения. Создай branch в своей системе контроля версий и начни переделывать программу. Если не получится, то branch можно спокойно удалить без риска для основной ветки разработки.
1
0 / 0 / 0
Регистрация: 25.06.2013
Сообщений: 112
01.12.2017, 13:25  [ТС] 5
Нашел такою тему:

Потоки, глобальные переменные и обмен данными между ними

Заинтересовала фраза:

Цитата Сообщение от aquaMakc Посмотреть сообщение
Создай класс с публичным свойством нужной тебе переменной и передавай этот класс в потоки. Т.к. передача класса осуществляется по ссылке, то в обоих потоках будет доступна одна и та-же переменная. Главное - на забыть таки синхронизировать доступ к этой переменной.
Можно, в принципе, и статический класс объявить с публичной статической переменной, тогда даже передавать ничего в потоки не надо будет, но это решение не приветствуется.
Кто нибудь возможно сможет привести пример создания класса с одной строковой переменной и код чтения ее из других потоков??? Запись данных в переменную из основного потока происходит аналогисно???

Добавлено через 22 часа 13 минут
Помогите плизз!
0
Администратор
Эксперт .NET
13851 / 11225 / 4569
Регистрация: 17.03.2014
Сообщений: 22,616
Записей в блоге: 1
01.12.2017, 13:32 6
Лучший ответ Сообщение было отмечено Yury Komar как решение

Решение

Anforcer,
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Sub StartThread
    Dim t As New Thread(AddressOf ThreadSub)
    Dim d As New Data With { .Str = "Test string" }
    t.Start(d) ' Запуск потока с передачей данных в поток
End Sub
 
Class Data
    Public Str As String
End Class
 
Sub ThreadSub(obj As Object)
    Dim d As Data = CType(obj, Data)
    Dim str As String = d.Str ' Чтение
End Sub
1
0 / 0 / 0
Регистрация: 25.06.2013
Сообщений: 112
04.12.2017, 20:14  [ТС] 7
Огромное спасибо. А нужно ли как то в потоках обрабатывать события связанные с занятостью переменной в другом потоке. Вкратце - мне необходимо , чтобы основной потом записывал в переменную значения, а дочерний считывал. Поясните пожалуйста
0
Администратор
Эксперт .NET
13851 / 11225 / 4569
Регистрация: 17.03.2014
Сообщений: 22,616
Записей в блоге: 1
05.12.2017, 00:02 8
Anforcer, зависит от переменной. Для простых типов ничего не нужно делать. Для сложных можно использовать критические секции (Lock), семафоры или ReaderWriterLockSlim.
1
0 / 0 / 0
Регистрация: 25.06.2013
Сообщений: 112
05.12.2017, 06:29  [ТС] 9
В моем случае это будет простая строковая переменная. В ее случае возможно теоретический одновременное обращение к ней на чтение и одновременную запись. Что в этом случае делать - обрамить операции чтения и записи exception?
0
Администратор
Эксперт .NET
13851 / 11225 / 4569
Регистрация: 17.03.2014
Сообщений: 22,616
Записей в блоге: 1
05.12.2017, 07:32 10
Anforcer, можно ничего не делать т.к. строки неизменяемы и для ссылочных типов гарантируется атомарность операций чтения/записи.
1
0 / 0 / 0
Регистрация: 25.06.2013
Сообщений: 112
06.12.2017, 08:09  [ТС] 11
Спасибо!!! Отлично!!!

Добавлено через 1 час 4 минуты
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  Sub StartCtmUserThread()
        Dim th As New Thread(AddressOf StartCtmUserThreadSub)
        Dim d As New Data With {.Str = ""}
        th.Start(d) ' Запуск потока с передачей данных в поток
    End Sub
 
    Sub StartCtmUserThreadSub(ByVal obj As Object)
        Dim thCtmUser = New _CtmUser
        Dim d As Data = CType(obj, Data)
        Dim str As String = d.Str ' Чтение
        thCtmUser.fmString = str
 
        Application.Run(thCtmUser)
    End Sub
 
    Class Data
        Public Str As String
    End Class
Я создал новый поток, перенес в него ссылку на строковую переменную. Открыл в новом потоке форму.
Завел на форме таймер и переодический считываю эту переменную и обновляю этой переменной текстовое поле.

Код на форме:

VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Public Class _CtmUser
    Public fmString As String
 
    Private Sub _CtmUser_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Timer1.Interval = 1000
        Timer1.Start()
    End Sub
 
    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Timer1.Stop()
        Label1.Text = fmString
        Timer1.Start()
    End Sub
End Class

Но ничего не работает. Label на форме не обновляется.
0
Администратор
Эксперт .NET
13851 / 11225 / 4569
Регистрация: 17.03.2014
Сообщений: 22,616
Записей в блоге: 1
06.12.2017, 14:02 12
Anforcer, label не меняется потому что не меняется переменная fmString. В приведенном примере вообще не видно соответствующего кода.
1
0 / 0 / 0
Регистрация: 25.06.2013
Сообщений: 112
06.12.2017, 16:02  [ТС] 13
Это тестовая программа. Вызывается форма с кнопкой. При нажатии на кнопку открывается форма в новом потоке и счетчик начинает записывать переменную в бесконечном цикле.

VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim mnloop As Double = 0
        Dim d As New Data With {.Str = ""}
        StartCtmUserThread()
        Do
            d.Str = mnloop.ToString
            ' прибавляем счетчик циклов программы
            mnloop += 1
            ' задержка между циклами
            Threading.Thread.Sleep(1000)
        Loop
    End Sub
 
    Sub StartCtmUserThread()
        Dim th As New Thread(AddressOf StartCtmUserThreadSub)
        Dim d As New Data With {.Str = ""}
        th.Start(d) ' Запуск потока с передачей данных в поток
    End Sub
 
    Sub StartCtmUserThreadSub(ByVal obj As Object)
        Dim thCtmUser = New _CtmUser
        Dim d As Data = CType(obj, Data)
        Dim str As String = d.Str ' Чтение
        thCtmUser.fmString = str
 
        Application.Run(thCtmUser)
    End Sub
 
    Class Data
        Public Str As String
    End Class
На форме открытой в новом потоке происходит переодической чтение этой переменной и вывод на Label.

VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
  Public fmString As String
 
    Private Sub _CtmUser_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Timer1.Interval = 1000
        Timer1.Start()
    End Sub
 
    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Timer1.Stop()
        Label1.Text = fmString
        Timer1.Start()
    End Sub
У меня есть сомнения в переменной fmString, она действительно должна быть public? Ну и в целом программа не работает - Label не изменяется.

Добавлено через 2 минуты
fmString присваивается в ссылка на переменную в классе в функции StartCtmUserThreadSub

VB.NET
1
thCtmUser.fmString = str
Или я что то не так делаю?
0
0 / 0 / 0
Регистрация: 25.06.2013
Сообщений: 112
09.02.2018, 21:13  [ТС] 14
Я нашёл способ передачи переменой в поток:

VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    Public objData as new Data
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim mnloop As Short = 0
        StartCtmUserThread()
        Do
            ObjData.Str = mnloop.ToString
            ' прибавляем счетчик циклов программы
            mnloop += 1
            ' задержка между циклами
            Threading.Thread.Sleep(1000)
        Loop
    End Sub
 
    Sub StartCtmUserThread()
        Dim th As New Thread(AddressOf StartCtmUserThreadSub)
        th.Start(objData) ' Запуск потока с передачей данных в поток
    End Sub
 
    Sub StartCtmUserThreadSub(ByVal obj As Object)
        Dim thCtmUser = New _CtmUser
        Dim d As Data = CType(obj, Data
        thCtmUser.fmData= d
 
        Application.Run(thCtmUser)
    End Sub
 
    Class Data
        Public Str As String
    End Class
Это код на форме:

VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
    Public fmData As object
 
    Private Sub _CtmUser_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Timer1.Interval = 1000
        Timer1.Start()
    End Sub
 
    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Timer1.Stop()
        Dim ff as object= ctype(fmData, Data)
        Label1.Text = ff.Str
        Timer1.Start()
    End Sub
У меня есть сомнения по правильности передачи переменной на форму из основного потока...
0
0 / 0 / 0
Регистрация: 25.06.2013
Сообщений: 112
20.02.2018, 15:42  [ТС] 15
Немного не правильно. Для того чтобы класс имел общие переменные с другими его копиями необходимо объявить его так:

VB.NET
1
2
3
Class Data
Private Shared Str As String
End Class
0
79 / 70 / 14
Регистрация: 18.01.2014
Сообщений: 341
20.02.2018, 16:08 16
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Создай branch в своей системе контроля версий и начни переделывать программу. Если не получится, то branch можно спокойно удалить без риска для основной ветки разработки.
А можно по-подробнее про этот branch, или ссылку, пожалуйста.
0
Администратор
Эксперт .NET
13851 / 11225 / 4569
Регистрация: 17.03.2014
Сообщений: 22,616
Записей в блоге: 1
20.02.2018, 16:13 17
_Radik_, какой системой контроля версий ты пользуешься? Если никакой, могу посоветовать только общее введение в тему - http://all-ht.ru/inf/prog/p_0_0.html
1
79 / 70 / 14
Регистрация: 18.01.2014
Сообщений: 341
20.02.2018, 16:15 18
OwenGlendower, да, ты прав, пока никакой, спасибо за ссылку
0
0 / 0 / 0
Регистрация: 29.08.2016
Сообщений: 119
21.02.2018, 15:18 19
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Anforcer, на этот вопрос невозможно дать ответ не изучив код приложения. Создай branch в своей системе контроля версий и начни переделывать программу. Если не получится, то branch можно спокойно удалить без риска для основной ветки разработки.
Можно узнать что такое branch и как им пользоваться?

Сорри, увидел Ваш ответ предыдущему пользователю
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.02.2018, 15:18

Как передать данные из дочерного потока в главный поток
Здравствуйте. Искал по форуму есть похожие темы но нет решения. Есть класс который загружает данные...

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

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

Выпадение из основного потока - пересечение
Здравствуйте! Сразу прилагаю код, а то уже 3 дня по вечерам бюсь об монитор головой и ничего...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.