Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# .NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
sptes
6 / 6 / 1
Регистрация: 16.02.2011
Сообщений: 146
1

Как усыплять дочерний поток реализуя управление элементами из главного потока методом Invoke

16.03.2012, 23:38. Просмотров 1927. Ответов 15
Метки нет (Все метки)

как управлять элементами из главного потока в дочернем? Если напишите методом Invoke, то объясните тогда - как заставять в определённых ситуациях усыплять дочерний поток?

Добавлено через 28 минут
Немного дополню: например если в методе, который перенаправляется в главный поток и там реализуются некие условия, после чего, если условие правильно, то дочерник поток поток должен засыпать. Как это реализовать?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.03.2012, 23:38
Ответы с готовыми решениями:

Invoke из главного потока во второй
озникла такая задача. Есть компонент, созданный в отдельном потоке(плеер). При...

Как запустить метод в главном потоке из не главного потока?
Прив. У меня такая трабла, пишу клиент, для игры на одном движке, и если от...

Начать выполнение главного потока после того, как выполнятся другие
Доброго времени суток. У меня вопрос, как сделать так, чтобы главный поток...

Invoke и новый поток
Пытаюсь запустить поток, в котором будут изменяться свойства listview. Но судя...

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

15
Mega-xaxax
38 / 38 / 1
Регистрация: 11.03.2012
Сообщений: 95
17.03.2012, 20:31 2
Усыпляйте с помощью WaitHandle, всю информацию о том как это сделать вы найдете тут:

http://www.rsdn.ru/article/dotnet/CSThreading1.xml

Обращение к графическим элементам осуществляется с помощью Invoke()
Обращение к переменным синхронизируйте с помощью lock:
C#
1
2
3
4
object locker = new object();
lock(locker) {
   //обращение к переменным, требующим синхронизации
}
1
sptes
6 / 6 / 1
Регистрация: 16.02.2011
Сообщений: 146
17.03.2012, 21:22  [ТС] 3
спасибо. А можете показать на примере, как реализовывать это с помощью WaitHandle?
0
Mega-xaxax
38 / 38 / 1
Регистрация: 11.03.2012
Сообщений: 95
17.03.2012, 21:35 4
Цитата Сообщение от sptes Посмотреть сообщение
спасибо. А можете показать на примере, как реализовывать это с помощью WaitHandle?
Сейчас попробую разобраться) Только читал об этом, если получиться приведу код

Добавлено через 11 минут
Вот такой вот код получился:

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
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
 
namespace WaitHandle
{
    class Program
    {
        static EventWaitHandle waitGoTrue = new EventWaitHandle(false, EventResetMode.AutoReset);
 
        static bool go = false;
 
        static void Main(string[] args)
        {
            // допустим, у нас есть поток, который ждет, когда же переменная go будет равна true
            Thread t = new Thread(StartWhenGoIsTrue);
            t.Start();
 
            // обратим внимание на то, что к моменту вызова следующей функции, поток уже работает и ждет сигнала
            Console.WriteLine("Нажмите кнопку и мы установим go в true");
            Console.ReadKey();
 
            go = true;
            // здесь мы что-то делаем и в какой-то промежуток времени go изменился на true, скажем об этом потоку
            waitGoTrue.Set();
 
            // не будем закрывать консоль, посмотрим на результат
            Console.ReadKey();
        }
 
        static void StartWhenGoIsTrue() {
            waitGoTrue.WaitOne();
            Console.WriteLine("Variable go is true. Yahooo!");
        }
    }
}
1
sptes
6 / 6 / 1
Регистрация: 16.02.2011
Сообщений: 146
17.03.2012, 22:05  [ТС] 5
Лан, пока не особа разобрался с графическими элементами, а с обычными, то так и без Invoke можно усыплять процесс напрямую . Спасибо всё равно за информацию, т.к. событие неплохое, пригодится.
0
Mega-xaxax
38 / 38 / 1
Регистрация: 11.03.2012
Сообщений: 95
17.03.2012, 22:13 6
Кажется я понял Вас, но не совсем. Опишите, в каких случаях Вы хотите усыпить поток и как при этом взаимодействуете с интерфейсом программы
0
sptes
6 / 6 / 1
Регистрация: 16.02.2011
Сообщений: 146
17.03.2012, 22:18  [ТС] 7
Поток изменяет текст на кнопки в зависимости от некоторых условий, которые определяются и находятся в главном методе, кнопки сами по себе визуальные, значит доступиться к ним и изменять их с помощью Invoke метода можно, но я не знаю, как усыпить этот поток так, чтобы он и взаимодействовал с кнопкой, выводил текст и так же засыпал. Если не совсем корректно объяснил, то распишу саму цель примера, т.к. это не программа особа, а так, закрепление материала.
0
Mega-xaxax
38 / 38 / 1
Регистрация: 11.03.2012
Сообщений: 95
17.03.2012, 22:20 8
Цитата Сообщение от sptes Посмотреть сообщение
Поток изменяет текст на кнопки в зависимости от некоторых условий, которые определяются и находятся в главном методе, кнопки сами по себе визуальные, значит доступиться к ним и изменять их с помощью Invoke метода можно, но я не знаю, как усыпить этот поток так, чтобы он и взаимодействовал с кнопкой, выводил текст и так же засыпал. Если не совсем корректно объяснил, то распишу саму цель примера, т.к. это не программа особа, а так, закрепление материала.
А новый текст для кнопки задается в главном потоке или в отдельном?
0
sptes
6 / 6 / 1
Регистрация: 16.02.2011
Сообщений: 146
17.03.2012, 22:34  [ТС] 9
В отдельном

Добавлено через 11 минут
Так же в отдельном потоке и идёт условие: Если условие срабатывает, то поток должен заснуть, если нет, то оставаться без изменений. Вот в этом и заключается сложность, что реализацию метода нельзя перенести в главный поток.
0
Mega-xaxax
38 / 38 / 1
Регистрация: 11.03.2012
Сообщений: 95
17.03.2012, 22:45 10
Вот что получилось (во вложении весь проект):

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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
 
namespace ButtonTextInvokeAndThreat
{
    public partial class frmMain : Form
    {
        // поток изменяющий текст на кнопке
        private Thread t = null;
        // сохраняет условие
        private string uslovie;
        // турникет для "условие изменилось"
        private EventWaitHandle uslovieIzmenilos = new EventWaitHandle(false, EventResetMode.AutoReset);
 
        public frmMain()
        {
            InitializeComponent();
        }
 
        // кнопка, при нажатии на которую применяется определенное условие
        private void btnSetIf_Click(object sender, EventArgs e)
        {
            // установим условие
            uslovie = txtBox.Text;
            uslovieIzmenilos.Set();
        }
 
        // запускаем поток при старте формы
        private void frmMain_Load(object sender, EventArgs e)
        {
            t = new Thread(ChangeTextOnButton);
            t.Start();
        }
 
        public void ChangeTextOnButton() {
            bool exit = false;
            while (!exit) {
                uslovieIzmenilos.WaitOne();
                if (btnButton.InvokeRequired) {
                    btnButton.Invoke(new ThreadStart(delegate {
                        if (uslovie == "") btnButton.Text = "Пустое условие";
                        if (uslovie == "1") btnButton.Text = "Вы ввели единичку";
                        if (uslovie == "2") btnButton.Text = "Вы ввели цифру два";
                        if (uslovie == "exit") exit = true; // выходим из потока
                    }));
                }
            }
        }
    }
}
Если это все равно не то, то объясните еще подробнее, тема-то интересная
1
Вложения
Тип файла: rar ButtonTextInvokeAndThreat.rar (33.2 Кб, 13 просмотров)
sptes
6 / 6 / 1
Регистрация: 16.02.2011
Сообщений: 146
17.03.2012, 22:53  [ТС] 11
Это всё замечательно, но где же то, чтобы дочерний поток засыпал? Имеет смысл занести в перебор кнопки текста разные названия, и при неком условии, например на внесении в поле условии кнопки 1000, то поток заснёт на 1 сек. А сам метод будет просто присваивать кнопке названия например из цикла.
0
Mega-xaxax
38 / 38 / 1
Регистрация: 11.03.2012
Сообщений: 95
17.03.2012, 22:59 12
Нифига я не понимаю, что Вы хотите, ну да ладно, вот последний вариант со спящим потоком, при условии, что ввели строку "1000" в txtBox.

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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
 
namespace ButtonTextInvokeAndThreat
{
    public partial class frmMain : Form
    {
        // поток изменяющий текст на кнопке
        private Thread t = null;
        // сохраняет условие
        private string uslovie;
        // турникет для "условие изменилось"
        private EventWaitHandle uslovieIzmenilos = new EventWaitHandle(false, EventResetMode.AutoReset);
 
        public frmMain()
        {
            InitializeComponent();
        }
 
        // кнопка, при нажатии на которую применяется определенное условие
        private void btnSetIf_Click(object sender, EventArgs e)
        {
            // установим условие
            uslovie = txtBox.Text;
            uslovieIzmenilos.Set();
        }
 
        // запускаем поток при старте формы
        private void frmMain_Load(object sender, EventArgs e)
        {
            t = new Thread(ChangeTextOnButton);
            t.Start();
        }
 
        public void ChangeTextOnButton() {
            bool exit = false;
            while (!exit) {
                uslovieIzmenilos.WaitOne();
                if (uslovie == "1000") Thread.Sleep(TimeSpan.FromSeconds(5)); // поток спит 5 секунд
 
                if (btnButton.InvokeRequired) {
                    btnButton.Invoke(new ThreadStart(delegate {
                        if (uslovie == "") btnButton.Text = "Пустое условие";
                        if (uslovie == "1") btnButton.Text = "Вы ввели единичку";
                        if (uslovie == "2") btnButton.Text = "Вы ввели цифру два";
                        if (uslovie == "exit") exit = true; // выходим из потока
                    }));
                }
            }
        }
    }
}
1
sptes
6 / 6 / 1
Регистрация: 16.02.2011
Сообщений: 146
17.03.2012, 23:19  [ТС] 13
Вот именно что условие, которое вы вынесли за метод Invoke должен быть именно в нём) и так же фигурировать с кнопкой, а не с полем, тем самым оно должно зависеть от изменения с графическим элементом, то-есть с кнпокой.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
            while (!exit)
            {
                uslovieIzmenilos.WaitOne();
                if (uslovie == "1000") Thread.Sleep(TimeSpan.FromSeconds(5)); // поток спит 5 секунд
 
                if (btnButton.InvokeRequired)
                {
                    btnButton.Invoke(new ThreadStart(delegate
                    {
                        if (uslovie == "")
                        {
                            btnButton.Text = "Пустое условие"; // <--
                            if (btnButton.Text != "Текст на кнопке") // <--
                                Thread.Sleep(300); // <--
                        }
                        if (uslovie == "1") btnButton.Text = "Вы ввели единичку";
                        if (uslovie == "2") btnButton.Text = "Вы ввели цифру два";
                        if (uslovie == "exit") exit = true; // выходим из потока
                    }));
                }
            }
Добавлено через 7 минут
Простите, что не с первого раза толково объяснил, я понял, что в предыдущем посте я неправильно изъяснился.
0
Mega-xaxax
38 / 38 / 1
Регистрация: 11.03.2012
Сообщений: 95
17.03.2012, 23:26 14
Ну, тогда это должно выглядеть вот так:

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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
 
namespace ButtonTextInvokeAndThreat
{
    public partial class frmMain : Form
    {
        // поток изменяющий текст на кнопке
        private Thread t = null;
        // сохраняет условие
        private string uslovie;
        // турникет для "условие изменилось"
        private EventWaitHandle uslovieIzmenilos = new EventWaitHandle(false, EventResetMode.AutoReset);
 
        public frmMain()
        {
            InitializeComponent();
        }
 
        // кнопка, при нажатии на которую применяется определенное условие
        private void btnSetIf_Click(object sender, EventArgs e)
        {
            // установим условие
            uslovie = txtBox.Text;
            uslovieIzmenilos.Set();
        }
 
        // запускаем поток при старте формы
        private void frmMain_Load(object sender, EventArgs e)
        {
            t = new Thread(ChangeTextOnButton);
            t.Name = "ThreadForSleep";
            t.Start();
        }
        
 
        private bool NeedToSleep = false;
        private object locker = new object(); // объект для блокировки переменной NeedToSleep
 
        public void ChangeTextOnButton() {
            bool exit = false;
            while (!exit) {
                lock (locker) { // устанавливаем блокировку NeedToSleep
                    if (NeedToSleep == true) { // если NeedToSleep == true, то поток спит
                        Thread.Sleep(300);
                    }
                    NeedToSleep = false; // после того как поспали, спать больше не надо
                }
                uslovieIzmenilos.WaitOne();
 
                if (btnButton.InvokeRequired) {
                    btnButton.Invoke(new ThreadStart(delegate {
                        if (uslovie == "") // если условие пустое
                        {
                            btnButton.Text = "Пустое условие"; // то изменяем текст на кнопке
                            if (btnButton.Text != "Текст на кнопке") { // если текст на кнопке не равен "Текст на кнопке"
                                lock (locker) {
                                    NeedToSleep = true; // то поспим чуть-чуть
                                }
                            }
                        }
                        if (uslovie == "1") btnButton.Text = "Вы ввели единичку";
                        if (uslovie == "2") btnButton.Text = "Вы ввели цифру два";
                        if (uslovie == "exit") exit = true; // выходим из потока
                    }));
                }
            }
        }
    }
}
1
sptes
6 / 6 / 1
Регистрация: 16.02.2011
Сообщений: 146
17.03.2012, 23:38  [ТС] 15
Спасибо, точно, надо было сразу так делать.
0
Mega-xaxax
38 / 38 / 1
Регистрация: 11.03.2012
Сообщений: 95
17.03.2012, 23:42 16
Пожалуйста. Минус этого кода, заключается в том, что все потоки, которые блокируются с помощью

C#
1
2
lock(locker) {
}
будут заблокированы, пока поток не проснется. Это происходит, потому что Thread.Sleep() находится внутри блока lock() {}, чтобы этого не происходило, код нужно переписать вот так:

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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
 
namespace ButtonTextInvokeAndThreat
{
    public partial class frmMain : Form
    {
        // поток изменяющий текст на кнопке
        private Thread t = null;
        // сохраняет условие
        private string uslovie;
        // турникет для "условие изменилось"
        private EventWaitHandle uslovieIzmenilos = new EventWaitHandle(false, EventResetMode.AutoReset);
 
        public frmMain()
        {
            InitializeComponent();
        }
 
        // кнопка, при нажатии на которую применяется определенное условие
        private void btnSetIf_Click(object sender, EventArgs e)
        {
            // установим условие
            uslovie = txtBox.Text;
            uslovieIzmenilos.Set();
        }
 
        // запускаем поток при старте формы
        private void frmMain_Load(object sender, EventArgs e)
        {
            t = new Thread(ChangeTextOnButton);
            t.Name = "ThreadForSleep";
            t.Start();
        }
        
 
        private bool NeedToSleep = false;
        private object locker = new object(); // объект для блокировки переменной NeedToSleep
 
        public void ChangeTextOnButton() {
            bool exit = false;
            while (!exit) {
                if (NeedToSleep) Thread.Sleep(300);
                lock (locker) { // устанавливаем блокировку NeedToSleep
                    if (NeedToSleep == true) { // если NeedToSleep == true, то поток спит
                        NeedToSleep = false; // после того как поспали, спать больше не надо
                    }
                }
                uslovieIzmenilos.WaitOne();
 
                if (btnButton.InvokeRequired) {
                    btnButton.Invoke(new ThreadStart(delegate {
                        if (uslovie == "") // если условие пустое
                        {
                            btnButton.Text = "Пустое условие"; // то изменяем текст на кнопке
                            if (btnButton.Text != "Текст на кнопке") { // если текст на кнопке не равен "Текст на кнопке"
                                lock (locker) {
                                    NeedToSleep = true; // то поспим чуть-чуть
                                }
                            }
                        }
                        if (uslovie == "1") btnButton.Text = "Вы ввели единичку";
                        if (uslovie == "2") btnButton.Text = "Вы ввели цифру два";
                        if (uslovie == "exit") exit = true; // выходим из потока
                    }));
                }
            }
        }
    }
}
Здесь я вынес Thread.Sleep за блок lock() {} - так делать можно, потому что мы считываем данные.
1
17.03.2012, 23:42
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.03.2012, 23:42

Многопоточность. Управление потоками из главного потока
Добра! Читал в интернете про потоки в Java и возник вопрос, например есть поток...

Как послать сигнал (самодельный) методом emit из потока в другой поток?
#include &quot;mainwindow.h&quot; #include &quot;ui_mainwindow.h&quot; ...

VC++6.0, как из порожденного потока прочитать переменную главного потока?
Visual C++ 6.0 SP5 Простое диалоговое окно, (MFC) созданное мастером среды VC...


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

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

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