52 / 13 / 0
Регистрация: 05.09.2014
Сообщений: 92
1

Использование класса object для передачи данных в поток

16.12.2014, 16:05. Показов 1701. Ответов 12
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте. Вот идея кода.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public partial class Form1 : Form
{
Thread поток=new Thread(последовательность);
 
public static void последовательность(object данные)
{
//Тут я хочу работать с элементами управления моего окна, ссылку на которое я пытаюсь передать через параметр функции.
}
private void button1_Click(object sender, EventArgs e)
        {
            
            поток.Start(this);
            
        }
}
Класс object лежит в основе иерархии классов и, следовательно, возникает справедливый вопрос - можно ли использовать его в качестве параметра для функции без потерь для передаваемого объекта другого класса ? Если да, то как его преобразовать обратно после передачи ссылки в поток ? Если нет, но подскажите пожалуйста как мне передать в поток ссылку на форму моего окна ?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.12.2014, 16:05
Ответы с готовыми решениями:

Использование перегруженного оператора ввода/вывода в поток базового класса для объекта производного класса
Здравствуйте! Можно ли использовать перегруженный оператор ввода/вывода в поток из базового класса...

Преобразование object -> byte[] -> object для передачи по сети
Дело такое: пишется прога для обращения к базе по сетке, ну а там нужна криптография!!!:confused:...

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

Использование DLL для приема-передачи данных в разных приложениях
Здраствуйте, я новичок в С++, недавно столкнулся с проблемой, не могу передать два числа типа int...

12
41 / 37 / 9
Регистрация: 01.02.2014
Сообщений: 825
16.12.2014, 16:12 2
ты можешь его вызывать из потока спокойно. Главное обезопасить от вызова одновременно более чем 1 потоком.
C#
1
2
3
4
this.Invoke((MethodInvoker)delegate()
{
вызывай любой объект формы.
});
И не нужно передавать лишних объектов.
1
Эксперт .NET
5540 / 4303 / 1218
Регистрация: 12.10.2013
Сообщений: 12,348
Записей в блоге: 2
16.12.2014, 16:20 3
Цитата Сообщение от Tini Посмотреть сообщение
как мне передать в поток ссылку на форму моего окна ?
Ятд, отвратительная идея. Форма (уровень отображения) и рабочий поток, лучше всего в отдельном классе,( логика реализации) не должны ничего знать друг о друге.
Создайте класс, в нем (через метод или конструктор) запускайте поток(и). А также событие(я), на которые и подпишитесь в форме и при их возникновении делайте с формой (ее элементами) то что требуется.
1
52 / 13 / 0
Регистрация: 05.09.2014
Сообщений: 92
16.12.2014, 18:19  [ТС] 4
Цитата Сообщение от MakcPletnev Посмотреть сообщение
ты можешь его вызывать из потока спокойно. Главное обезопасить от вызова одновременно более чем 1 потоком.
Код C#
1
2
3
4
this.Invoke((MethodInvoker)delegate()
{
вызывай любой объект формы.
});
И не нужно передавать лишних объектов.
Начал разбираться с this.Invoke и ... возникли сложности. В примерах, на которые я натолкнулся, this.Invoke используется следующим образом: есть основной поток, вызываемый и отдельная функция. this.Invoke используется в вызываемом потоке, чтобы подключить отдельную функцию. Здесь появляется вопрос, касающийся моей проблемы: в такой ситуации функция будет выполняться ресурсами основного потока или она просто использует его среду, а выполняет ее все же вызываемый поток ? Из вашего ответа не совсем ясно, а в попытках понять самостоятельно я потерпел неудачу, как именно использовать приведенный вами код ? В моем примере "последовательность" является статическим свойством класса и this в нем использовать бессмысленно. Использовать this.Invoke, чтобы запустить поток - вообще глухая затея. Покажите пожалуйста как использовать ваш пример в моем коде.
0
Эксперт .NET
5540 / 4303 / 1218
Регистрация: 12.10.2013
Сообщений: 12,348
Записей в блоге: 2
16.12.2014, 18:45 5
Цитата Сообщение от Tini Посмотреть сообщение
this.Invoke используется в вызываемом потоке, чтобы подключить отдельную функцию.
Tini, данная конструкция, как правило, используется для маршалинга обращений к-либо потока (потоков) к объектам пользовательского интерфейса (и основному потоку приложения).
То есть, говоря проще, через данную конструкцию мы можем обратиться из другого потока к форме (и/или ее элементам) и что-то с ними сделать, поскольку прямо обратиться к ним из другого потока (не из того, в котором они созданы) мы не можем (вернее, можем, но все накроется медным тазом, как пишут умные люди).
Использовать данную конструкцию для запуска потока - об этом я не слышал (если только с экземплярами делегатов).
1
52 / 13 / 0
Регистрация: 05.09.2014
Сообщений: 92
16.12.2014, 18:48  [ТС] 6
Цитата Сообщение от insite2012 Посмотреть сообщение
Ятд, отвратительная идея. Форма (уровень отображения) и рабочий поток, лучше всего в отдельном классе,( логика реализации) не должны ничего знать друг о друге.
Создайте класс, в нем (через метод или конструктор) запускайте поток(и). А также событие(я), на которые и подпишитесь в форме и при их возникновении делайте с формой (ее элементами) то что требуется.
Да я ведь не против, поэтому и записал рабочие функции в одно пространство имен, а создание окна - в другое. Пытаюсь как-то разделить и сделать так, чтобы отдельные элементы программы взаимодействовали друг с другом через возвращаемые значения, либо через свойства классов или самих объектов. Просто из-за неопытности многие вещи еще не знаю. Идея реагирования на события самой формой мне нравится, но это не будет затратней с точки зрения ресурсов ? Форма ведь должна будет постоянно "сканировать" состояние своих элементов, разве не лучше менять их через свойства ? В любом случае постарайтесь понять - я не могу "связать" окно с вызываемым потоком. Насчет логики реализации - то есть вы предлагаете, чтобы через button1_Click запускалась функция, определенная в другом файле и запускающая новый поток, который в свою очередь выполняет функции из третьего места ? Ну да, эстетично.
0
Эксперт .NET
5540 / 4303 / 1218
Регистрация: 12.10.2013
Сообщений: 12,348
Записей в блоге: 2
16.12.2014, 18:53 7
Цитата Сообщение от Tini Посмотреть сообщение
Идея реагирования на события самой формой мне нравится, но это не будет затратней с точки зрения ресурсов ? Форма ведь должна будет постоянно "сканировать" состояние своих элементов, разве не лучше менять их через свойства ?
Никаких затрат. Все будет работать. И о каком сканировании речь. Форма просто подписалась на к-либо события, и все. И если они не произошли, она и не отреагировала. Вся работа программы вообще основана на событиях, вы разве этого не знали? Нажали кнопку - произошло событие, и если есть обработчик - что-то сработало. Так чем ваши пользовательские события будут затратнее встроенных в FW?
Чуть позже, если надо, могу сделать вам простенький пример.
1
52 / 13 / 0
Регистрация: 05.09.2014
Сообщений: 92
16.12.2014, 19:06  [ТС] 8
Цитата Сообщение от insite2012 Посмотреть сообщение
Никаких затрат. Все будет работать. И о каком сканировании речь. Форма просто подписалась на к-либо события, и все. И если они не произошли, она и не отреагировала. Вся работа программы вообще основана на событиях, вы разве этого не знали? Нажали кнопку - произошло событие, и если есть обработчик - что-то сработало. Так чем ваши пользовательские события будут затратнее встроенных в FW?
Чуть позже, если надо, могу сделать вам простенький пример.
Был бы очень благодарен. И также я был очень благодарен за самый простенький пример использования Invoke, потому что у меня не получается этого понять. Запускаемый поток является статическим методом. Я не знаю, как "указать" ему на объект, из которого он был запущен или на его методы.
0
41 / 37 / 9
Регистрация: 01.02.2014
Сообщений: 825
16.12.2014, 21:34 9
Tini, не надо указывать ему ни на что, в функцию, которая вызывается из потока добавь
C#
1
2
3
4
5
6
7
8
9
10
this.Invoke((MethodInvoker)delegate()
{
И тут любой элемент формы вызывается от имени основного потока.
-> функции тоже будут выполняться в основном потоке, поэтому надо смотреть куда и как вставлять этот метод.
});
Можно сделать так:
this.Invoke((textBox1 или даже по моему на свойство можно поставить textBox1.Text)delegate()
{
 
});
Все очень легко. Просто нужно повнимательнее использовать данный метод, потому что большая нагрузка на основной поток будет фризить форму.
1
52 / 13 / 0
Регистрация: 05.09.2014
Сообщений: 92
16.12.2014, 23:06  [ТС] 10
Вставил - не получилось. Я и в вызываемую дополнительным потоком функцию вставить пробовал, и в функцию вызывающую новый поток, в конце уже с дури и в сам начальный код вставлял - не нравится им this. Значит все-таки нагрузка идет на основной поток. Понимаете, я и хочу добиться, чтобы главную форму вообще не загружать, а то создал окно с одним потоком, а программа у меня качает данные с сайта из интернета, то есть, как я слышал их принято называть, парсер. А для остановки этой самой программы нужно как раз нажать на одну из кнопок на форме. Понимаете комичность ситуации.После этого и открыл для себя чудесный мир потоков. Плюс ко всему пытаюсь еще и грамотно писать, то есть разделять программу на отдельные логические блоки. Да вот беда - знаний мало, поэтому и плюхаюсь в смешных вопросах. Мне почему-то кажется, что вы не читали наш диалог с insite, если я ошибся, то извиняюсь. Вы предлагаете поставить ваш код в вызываемую новым потоком функцию, но она ведь является статическим методом, и в области этой самой функции this кажется ей птенцом кукушки. Я в интернете полазил и убедился, что обратиться как к статическому методу класса, так и к методу отдельного экземпляра очень просто, но я никак не могу понять: как обратиться именно этому моему экземпляру окна ? Конструктор создает его через InitializeComponent(). Где же имя ? Понимаете ? Я уверен, что вы знаете ответ, просто, возможно, я неправильно излагал суть проблемы. То есть при запуске программы конструктор создает экземпляр Form1, с которым я работаю. Где найти его имя в конструкторе ? Или как дать ему имя ? А то получается, что методы и поля экземпляра есть, а самого экземпляра нет.
0
Эксперт .NET
5540 / 4303 / 1218
Регистрация: 12.10.2013
Сообщений: 12,348
Записей в блоге: 2
16.12.2014, 23:42 11
MakcPletnev, я бы вас попросил, вы или пишите как положено, или не пишите вообще, чтобы не вводить новичков в заблуждение.
Цитата Сообщение от MakcPletnev Посмотреть сообщение
или даже по моему на свойство можно поставить
Такие фразы никакой помощи не дают, а еще больше запутывают. Да и вам не делают чести, раз вы сами не знаете, так это или только "по вашему".
Tini, вот вам пример. Тестовый. Форма, две кнопки и два лейбла, с именами по умолчанию. При нажатии любой из них создается экземпляр класса, делается подписка на событие в классе и вызывается его метод, который создает и запускает поток. Этот поток в цикле генерирует событие, при наступлении которого соответствующий лейбл меняет свое значение. Разбирайтесь, там есть много комментариев.
C#
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
using System.Threading;
using System.Threading.Tasks;
 
namespace FormAndThreads {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
            button1.Click += new EventHandler(button1_Click);
            button2.Click += new EventHandler(button2_Click);
        }
        //Нажатие кнопки 1
        void button2_Click(object sender, EventArgs e) {
            //Экземпляр класса
            TestClass test = new TestClass(50);
            //Подписка на событие класса(через лямбда выражение)
            test.classEvent += (s, arg) => {
                //Обращение к элементу формы через Invoke() через лямбда выражение
                //Из аргумента события извлекается переменная, переданная из потока
                label1.Invoke((Action)(() => { label1.Text = arg.Result.ToString(); }));
            };
            //Вызов метода класса
            test.Run();
        }
        //Нажатие кнопки 2
        void button1_Click(object sender, EventArgs e) {
            //Экземпляр класса
            TestClass test = new TestClass(100);
            //Подписка на событие класса(через лямбда выражение)
            test.classEvent += (s, arg) => {
                //Обращение к элементу формы через Invoke() через лямбда выражение
                //Из аргумента события извлекается переменная, переданная из потока
                label2.Invoke((Action)(() => { label2.Text = arg.Result.ToString(); }));
            };
            //Вызов метода класса
            test.Run();
        }
    }
    //Тестовый класс
    public class TestClass {
        //Событие в классе
        public event EventHandler<TestEventArgs> classEvent;
        //Поле типа int
        private int result;
        //Конструктор
        public TestClass(int res) {
            result = res;
        }
        //public метод, запускающий отдельный фоновый поток
        public void Run() {
            new Thread(() => {
                //Цикл внутри потока
                for (int i = 0; i < result; i++) {
                    //Проверка события на наличие подписки и вызов
                    if (classEvent != null) {
                        classEvent(this, new TestEventArgs(i));
                    }
                    Thread.Sleep(500);
                }
            }) { IsBackground = true }.Start();
 
        }
    }
    //Класс для аргумента события
    public class TestEventArgs : EventArgs {
        public readonly int Result;
        public TestEventArgs(int r) {
            Result = r;
        }
    }
}
1
52 / 13 / 0
Регистрация: 05.09.2014
Сообщений: 92
17.12.2014, 13:04  [ТС] 12
Спасибо большое, сейчас голова уже не варит, спать пора, но завтра обязательно подробно изучу ваш пример.

Добавлено через 13 часов 9 минут
Ууууу ... день у меня точно займет разбор вашего примера. Много новой информации.
0
52 / 13 / 0
Регистрация: 05.09.2014
Сообщений: 92
11.06.2015, 02:31  [ТС] 13
В продолжение темы. Уважаемый Insite, а почему вы реализовываете взаимодействие именно через событие ? Я попытался создать некий аналог взаимодействия элементов формы с созданным потоком и у меня получилось.
C#
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
32
33
34
35
36
37
38
39
40
41
42
43
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace поток
{
    public partial class Form1 : Form
    {
        Функция фун = new Функция();
        bool сущ = false;
        public Form1()
        {
            InitializeComponent();
            button1.Click+=button1_Click;
            button2.Click+=button2_Click;
            
        }
 
        
 
        private void button1_Click(object sender, EventArgs e)
        {
            int a1, a2, a3;
            фун.присвоим(a1 = Int32.Parse(textBox1.Text), a2 = Int32.Parse(textBox2.Text), a3 = Int32.Parse(textBox3.Text));
            if(сущ==false)
            {
                сущ=true;
                фун.запуск_потока();
            }   
            else textBox4.Text = фун.получить_данные().ToString();
        }
        private void button2_Click(object sender, EventArgs e)
        {
            
        }
    }
}
А это вызываемый класс
C#
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
32
33
using System;
using System.Threading;
 
/// <summary>
/// Сводное описание для Class1
/// </summary>
public class Функция
{
    int д1;
    int д2;
    int д3;
    int рез;
    public int получить_данные()
    {
        return рез;
    }
    
    public void присвоим(int d1, int d2, int d3)
    {
        д1 = d1;
        д2 = d2;
        д3 = d3;
    }
    public void запуск_потока()
    {
        Thread поток = new Thread(действия);
        поток.Start();
    }
    void действия()
    {
        рез=д1 + д2 - д3;
    }
}
Чем плох мой подход ?

Добавлено через 21 час 19 минут
Никакой реакции - настолько плохой код ?)))
0
11.06.2015, 02:31
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.06.2015, 02:31
Помогаю со студенческими работами здесь

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

Использование имя object в свойстве класса
День добрый. Столкнулся с проблемой: пишу вк бота, он скидывает json на мой сервер. Сам запрос...

Использование класса для хранения данных.
Можно ли использовать класс как структуру (struct) для хранения и преобразования данных? Все...

Использование каналов передачи данных
Сервер вводит в режиме диалога некоторое сообщение строкового типа и печатает его. С помощью...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru