powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Передача данных между потоками
15 сообщений из 15, страница 1 из 1
Передача данных между потоками
    #38362003
Фотография palich12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте, Коллеги!
Есть поток слушающий порт, когда приходит сообщение, поток создает событие и кидает в него аргумент. Второй поток обслуживающий форму получает событие, но не может обратиться к полученному параметру. Ловлю ошибку
авторВызывающий поток не может получить доступ к данному объекту, так как владельцем этого объекта является другой поток.
Такая ошибка возникает обычно когда к контролу из левого потока обратиться пытаешься, но там это решается при помощи invoke, а тут просто класс с данными, у него нет никакого invoke. Как же тогда передавать данные между потоками?

P.S.
Дело в том, что я хочу сделать отдельную библиотеку для работы с этим портом, а форма просто временная, поэтому нужно именно передавать данный от потока к потоку, а не писать данные вторым потоком прямо в форму при помощи invoke
...
Рейтинг: 0 / 0
Передача данных между потоками
    #38362032
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
palich12,
автор поток создает событие и кидает в него аргумент
авторВторой поток обслуживающий форму получает событие
автор а тут просто класс с данными
ничего не ясно. что за потоки что за классы, что за события....
про invoke как (передача) данных, это мелкий частный случай в контексте темы передачи,
есть куча всяких вариантов например как SynchronizationContext и тд..
...
Рейтинг: 0 / 0
Передача данных между потоками
    #38362041
Фотография palich12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степи,
Вот код потока слушателя
Код: 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.
 void ServerThreadMethod()
        {
            string exceptmessage = "";
            try
            {
                while (IsRunning)
                {
                    IPEndPoint rep = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 1);
                    byte[] packege = Listener.Receive(ref rep);
                    
                    
                    MostikServerEventArg arg = PackageWorking(packege, rep);
                    if( arg != null )
                        OnRaiseMosticServerEvent(arg);
                        

                }
            }
            catch (Exception ex)
            {
                exceptmessage = ex.Message;
            }

            if (IsRunning)
                ServerStop();
            OnRaiseMosticServerEvent(new MostikServerEventArg("Сервер остановлен: " + exceptmessage));
           
        }



А вот код обработчика события, который выполняется основным потоком
Код: 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.
private void OnServerEvent( object sender, MostikServerEventArg arg )
        {
            if (arg.Type == MostikServerEventType.ServerEvent)
                OutputText.Text += "\r\n" + arg.ServerMessage;
            else if( arg.Type == MostikServerEventType.GotPackage )
                OutputText.Text += "\r\n" 
                    + arg.Package.MostikEndPoint.Address.ToString() 
                    + ":" + arg.Package.MostikEndPoint.Port.ToString() + " " + BitConverter.ToString( arg.Package.Input );
            else if( arg.Type == MostikServerEventType.GotUnknownData )
                OutputText.Text += "\r\n" + arg.ServerMessage;
            else if( arg.Type == MostikServerEventType.MostikConfirm )
                OutputText.Text += "\r\n Мостик " + arg.MostikInhere.GetName() + " принял команду";
            else if (arg.Type == MostikServerEventType.MostikConnected)
            {
                OutputText.Text += "\r\n Мостик " + arg.MostikInhere.GetName() + " подключен";
                MostiksList.Items.Add( arg.MostikInhere.GetName() );
            }
            else if (arg.Type == MostikServerEventType.MostikDisconnected)
            {
                OutputText.Text += "\r\n Мостик " + arg.MostikInhere.GetName() + " отключен";
                MostiksList.Items.Clear();
                foreach (Mostik m in server.ConnectedMostiks)
                    MostiksList.Items.Add(m.GetName());
            }
            else if( arg.Type == MostikServerEventType.MostikNotUnderstand)
                OutputText.Text += "\r\n Мостик " + arg.MostikInhere.GetName() + " не смог распознать команду";
            else if( arg.Type == MostikServerEventType.NoAnswer )
                OutputText.Text += "\r\n Мостик " + arg.MostikInhere.GetName() + " не ответил на запрос";
        }


При первом же обращении к MostikServerEventArg arg происходит исключение
VSВызывающий поток не может получить доступ к данному объекту, так как владельцем этого объекта является другой поток.
...
Рейтинг: 0 / 0
Передача данных между потоками
    #38362052
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
palich12,
я так и знал ((....
вот чистая рыба по вашей беде..
Код: 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.
 private void button1_Click(object sender, EventArgs e)
        {
            var sc = SynchronizationContext.Current;
            var a = new WorkingAss();
            a.APush += i => sc.Send(delegate { label1.Text = i.ToString(); }, null);
            new Thread(iss =>
                {
                    var i = 0;
                    while (true)
                    {
                        ((WorkingAss)iss).Push(++i);
                    }
                }).Start(a);

        }
        class WorkingAss
        {
            public event Action<int> APush;
            public void Push(int value)
            {
                if (APush != null)
                {
                    APush(value);
                }
            }
        }
...
Рейтинг: 0 / 0
Передача данных между потоками
    #38362053
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
palich12,авторА вот код обработчика события, который выполняется основным потоком гыгы ))
...
Рейтинг: 0 / 0
Передача данных между потоками
    #38362136
Фотография Torre
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
palich12, только static delegate thread safe
...
Рейтинг: 0 / 0
Передача данных между потоками
    #38362390
Фотография skole
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степи, SynchronizationContext все-таки более предназначен для взаимодействия с UI (SynchronizationContext.Current) , в других случаях лучше использовать лямбда-выражения.
...
Рейтинг: 0 / 0
Передача данных между потоками
    #38362393
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
skole,
так у та и возникли проблемы с ui, или вы тоже считаете что обработчик события выполняется в основном потоке?
...
Рейтинг: 0 / 0
Передача данных между потоками
    #38362442
Фотография skole
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, пардон, точно
...
Рейтинг: 0 / 0
Передача данных между потоками
    #38362671
LameUser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тынц

Для ленивых
An extension method would generally be the way to go, since you're always going to want to perform an action on an ISynchronizeInvoke interface implementation, it's a good design choice.

You can also take advantage of anonymous methods (closures) to account for the fact that you don't know what parameters to pass to the extension method; the closure will capture the state of everything needed.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
// Extension method.
static void SynchronizedInvoke(this ISynchronizeInvoke sync, Action action)
{
    // If the invoke is not required, then invoke here and get out.
    if (!sync.InvokeRequired)
    {
        // Execute action.
        action();

        // Get out.
        return;
    }

    // Marshal to the required context.
    sync.Invoke(action, new object[] { });
}


You'd then call it like this:

Код: c#
1.
2.
3.
4.
private void SetText(string text)
{
    textBox1.SynchronizedInvoke(() => textBox1.Text = text);
}

...
Рейтинг: 0 / 0
Передача данных между потоками
    #38365740
Фотография palich12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степиskole,
так у та и возникли проблемы с ui, или вы тоже считаете что обработчик события выполняется в основном потоке?
Спасибо большое, но может посоветуете, как добиться того, чтобы событие обрабатывалось в основном потоке?
...
Рейтинг: 0 / 0
Передача данных между потоками
    #38367598
Фотография palich12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нашел форум, где тоже обсуждалась аналогичная задача, там есть пара решений, не очень красивые на мой взгляд, но лучше чем ничего. Вот если кому нужно http://www.gotdotnet.ru/forums/3/93216/
...
Рейтинг: 0 / 0
Передача данных между потоками
    #38368144
Фотография Torre
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так что ли надо?

Код: 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.
public delegate void MainDelegate(int i);
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            Thread t = new Thread(StartTask);
            t.Start();
        }

        public void StartTask()
        {
            Runner r = new Runner();
            r.OnUpdate += new MainDelegate(this.UpdateForm);
            r.Run();
        }

        public void UpdateForm(int i)
        {
            this.Invoke(new Action(() =>
            {
                lblResult.Text = i + " times";
            }));
        }
    }

    public class Runner
    {
        public event MainDelegate OnUpdate;
        public void Run()
        {
            for (int i = 0; i < 10; i++)
            {
                if (OnUpdate != null)
                {
                    OnUpdate(i);
                }

                Thread.Sleep(1000);
            }
        }
    }



...
Рейтинг: 0 / 0
Передача данных между потоками
    #38368280
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
palich12Где-то в степиskole,
так у та и возникли проблемы с ui, или вы тоже считаете что обработчик события выполняется в основном потоке?
Спасибо большое, но может посоветуете, как добиться того, чтобы событие обрабатывалось в основном потоке?
Да никак, Вы инициализируете событие указателем на кусок кода с определенной сигнатурой, которое и исполнится в определенный момент, мало того вы в сигнатуру при вызове тащите this, то есть вы можете из обработчика изменить состояние чего то что породило событие, ( хотя и не следует это делать) , а теперь подумайте как это все хозяйство протащить в основной поток?
следует акцентироваться на своих желаниях, или событие ( в классическом виде) или подать сигнал кому то, что что то произошло в потоке ( костровая почта, маршалинг, меседж, и т.д) и двигать поток дальше.., советую взять тайм аут и вернуться к истокам ( базовым знаниям) подшлифовать их честно скажу - незападло( нем мог подобрать синоним, извините) даже гуру..
...
Рейтинг: 0 / 0
Передача данных между потоками
    #38368390
LameUser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
palich12Нашел форум, где тоже обсуждалась аналогичная задача, там есть пара решений, не очень красивые на мой взгляд, но лучше чем ничего. Вот если кому нужно http://www.gotdotnet.ru/forums/3/93216/

Там делается все то же самое, что написал и я в прердыдущем посте, но более коряво. (В те года как я понимаю расширяющих методов не было).
Я же вам написал нормально решение, для любого типа контрола, которое взято со stackoverflow.com.
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Передача данных между потоками
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]