Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/11: Рейтинг темы: голосов - 11, средняя оценка - 5.00
 Аватар для Pendragon
1 / 1 / 0
Регистрация: 09.03.2013
Сообщений: 38

Синхронизация потоков

09.03.2013, 19:55. Показов 2463. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Я понимаю, что подобные вопросы уже много раз задавались, но перечитав подобные темы та и другую литературу, так и не смог найти решения для моей задачи.
Вообщем в от в чем дело! У меня есть 2 потока. Первый это основной поток, который запускается при запуске программы и второй, который я создаю сам. Проблема в том, что я так и не понял, как правильно их синхронизировать.

У меня есть pictureBox, который я передаю в свой поток, который в свою очередь передвигает ее по канве. Проблема в том, что выбивает такову ошибку "Недопустимая операция в нескольких потоках: попытка доступа к элементу управления 'pictureBox1' не из того потока, в котором он был создан."

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

Заранее спасибо!!

Код осн. программы:
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
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;
using System.Threading;
using System.Timers;
 
namespace  LB_03
{
    public partial class Form1 : Form
    {
        PictureBox img = new PictureBox();
        public Form1()
        {           
            InitializeComponent();
            
 
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            img = pictureBox1;
 
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            Thread MainThrd = Thread.CurrentThread;
            EnemyThread t1 = new EnemyThread(img);
            t1.thrd.IsBackground = true;
            t1.Priority = ThreadPriority.Lowest;
            t1.thrd.Join();
 
        }
 
        private void timer1_Tick(object sender, EventArgs e)
        {
        }
 
        private void pictureBox1_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
34
35
36
37
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Drawing;
 
 
namespace LB_03
{
    class EnemyThread
    {
        public PictureBox img;
        public Thread thrd;
 
        public EnemyThread(PictureBox img)
        {
            this.img = img;
            thrd = new Thread(new ThreadStart(this.run));
            thrd.Start();
        }
 
        void run()
        {
            for (int i = 0; i < 40; i += 1)
            {
                    Thread.Sleep(100);
                    img.Location = new Point(img.Location.X + 10, img.Location.Y);
            }
 
        }
 
        public ThreadPriority Priority { get; set; }
    }
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
09.03.2013, 19:55
Ответы с готовыми решениями:

Синхронизация потоков на элементарном уровне (переключение потоков)
в общем разбираюсь с потоками, на сколько понял мне нужен lock Вот имеется просто пример public void RunAdd() ...

Синхронизация потоков: проблема гонки потоков
Есть проблема в синхронизации потоков, которую я не знаю, как решить. Точнее у меня получается типичная гонка потоков. Есть функция,...

Синхронизация потоков c#
Всем привет) Решил написать программу, которая в несколько потоков будет выкачивать торрент файлы с трекера, но возникла проблема - в...

6
1 / 3 / 2
Регистрация: 30.12.2010
Сообщений: 45
10.03.2013, 00:57
делегат + Invoke и все будет работать.
0
 Аватар для Pendragon
1 / 1 / 0
Регистрация: 09.03.2013
Сообщений: 38
10.03.2013, 01:54  [ТС]
делегат + Invoke и все будет работать.
В том то и дело, что я прошу мне показать как работать с этим конкретно для моей задачи и дать обьяснения.
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
10.03.2013, 02:25
мм, доступ к контролу всегда должен производиться из того же потока, в котором он было создан.Для этого нужен метод Invoke.
C#
1
2
3
4
5
6
7
8
9
10
11
     void run()
        {
            for (int i = 0; i < 40; i += 1)
            {
                    Thread.Sleep(100);
                        if (img.InvokeRequired)
                            img.Invoke(()=>{ img.Location = new Point(img.Location.X + 10, img.Location.Y);});
                            else 
                    img.Location = new Point(img.Location.X + 10, img.Location.Y);
            } 
        }
Добавлено через 2 минуты
Хотя else и после можно убрать - это для более сложных случаев, на мой взгляд.

Добавлено через 1 минуту
Кстати, синхронизация тут не при чем. Просто межпотоковое взаимодействие.

Добавлено через 23 минуты
по памяти писал, проверил- не работает, вот исправленный вариант:
C#
1
2
3
4
5
6
7
8
9
10
11
 void run()
        {
            for (int i = 0; i < 40; i += 1)
            {
                    Thread.Sleep(100);
                        if (img.InvokeRequired)
                            img.Invoke(new Action(()=>{ img.Location = new Point(img.Location.X + 10, img.Location.Y);}));
                            else 
                    img.Location = new Point(img.Location.X + 10, img.Location.Y);
            } 
        }
1
Заблокирован
10.03.2013, 02:30
1.
Цитата Сообщение от Pendragon Посмотреть сообщение
t1.thrd.Join();
смысл создавать другой поток, если ты все равно блокируешь основной?
2.
Цитата Сообщение от Pendragon Посмотреть сообщение
public ThreadPriority Priority { get; set; }
совсем ничего не делает, да вообще лучше не менять приоритеты потоков самостоятельно.
3.
Цитата Сообщение от Pendragon Посмотреть сообщение
Thread MainThrd = Thread.CurrentThread;
эта строка тут тоже совсем ни к чему.
4.
Цитата Сообщение от Pendragon Посмотреть сообщение
PictureBox img = new PictureBox();
Зачем? new PictureBox(); просто создал объект и тут же превратил его в мусор. Хотя оптимизатор конечно может справиться с таким беспределом.

//Код EnemyThread
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
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
 
namespace LB_03
{
    class EnemyThread
    {
        private readonly PictureBox _img;
        private readonly  Thread _thrd;
 
        public EnemyThread(PictureBox img)
        {
            _img = img;
            _thrd = new Thread(Run) {IsBackground = true};
        }
 
        public void Start()
        {
            _thrd.Start();
        }
 
        private void Run()
        {
            var action = new Action(ChangeLocation);
            for (int i = 0; i < 40; i += 1)
            {
                Thread.Sleep(100);
                if (_img.InvokeRequired) //требуется ли обращатся к элементу управления через Invoke()?
                    _img.Invoke(action); //говорим системе выполнить делегат action в контексте потока, который создал Handle PictureBox
                else
                    ChangeLocation();
            }
        }
 
        private void ChangeLocation()
        {
            _img.Location = new Point(_img.Location.X + 10, _img.Location.Y);
        }
    }
}
Добавлено через 1 минуту
код формы
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
namespace LB_03
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
 
            private void button1_Click(object sender, EventArgs e)
            {
                EnemyThread t1 = new EnemyThread(pictureBox1);
                t1.Start();
            }
 
        }
    }
1
 Аватар для Pendragon
1 / 1 / 0
Регистрация: 09.03.2013
Сообщений: 38
10.03.2013, 02:56  [ТС]
IamRain и loro
Огромное вам Вам спасибо!!
0
Заблокирован
10.03.2013, 03:11
Pendragon, кстати если ты оставишь Join() и будешь использовать Invoke- это хорошая иллюстрация дедлока. Потому что Invoke будет ждать выполнения делегата в потоке, который заблокирован и ждет завершения второго потока.
В таком случае можно использовать BeginInvoke, но плавного движения не будет.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
10.03.2013, 03:11
Помогаю со студенческими работами здесь

Синхронизация потоков
Есть ли возможность в C# сделать часть кода потока защищенным от прерывания другими потоками. Lock не подходит, т.к. потоки не используют...

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

Синхронизация потоков
Не так давно начал заниматься c#.. возникла следующее недопонимание потоков. Программа ищет в цикле случайное число от 0 до 10, цикл...

Синхронизация потоков
Привет. Проблема: рандомные потоки возвращают одинаковые значения, хотя синхронизацию сделал. Для примера код такой: private...

Синхронизация потоков
Здравствуйте! Есть задача создать два потока в каждом из которых будет бегущая строка(одна справа налево, вторая слева направо). Бегающие...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru