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

P.S.
Дело в том, что я хочу сделать отдельную библиотеку для работы с этим портом, а форма просто временная, поэтому нужно именно передавать данный от потока к потоку, а не писать данные вторым потоком прямо в форму при помощи invoke
...
Рейтинг: 0 / 0
10.08.2013, 22:57
    #38362032
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Передача данных между потоками
palich12,
автор поток создает событие и кидает в него аргумент
авторВторой поток обслуживающий форму получает событие
автор а тут просто класс с данными
ничего не ясно. что за потоки что за классы, что за события....
про invoke как (передача) данных, это мелкий частный случай в контексте темы передачи,
есть куча всяких вариантов например как SynchronizationContext и тд..
...
Рейтинг: 0 / 0
10.08.2013, 23:16
    #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
10.08.2013, 23:26
    #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
10.08.2013, 23:30
    #38362053
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Передача данных между потоками
palich12,авторА вот код обработчика события, который выполняется основным потоком гыгы ))
...
Рейтинг: 0 / 0
11.08.2013, 02:01
    #38362136
Torre
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Передача данных между потоками
palich12, только static delegate thread safe
...
Рейтинг: 0 / 0
11.08.2013, 18:22
    #38362390
skole
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Передача данных между потоками
Где-то в степи, SynchronizationContext все-таки более предназначен для взаимодействия с UI (SynchronizationContext.Current) , в других случаях лучше использовать лямбда-выражения.
...
Рейтинг: 0 / 0
11.08.2013, 18:32
    #38362393
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Передача данных между потоками
skole,
так у та и возникли проблемы с ui, или вы тоже считаете что обработчик события выполняется в основном потоке?
...
Рейтинг: 0 / 0
11.08.2013, 20:17
    #38362442
skole
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Передача данных между потоками
А, пардон, точно
...
Рейтинг: 0 / 0
12.08.2013, 07:57
    #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
14.08.2013, 10:44
    #38365740
palich12
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Передача данных между потоками
Где-то в степиskole,
так у та и возникли проблемы с ui, или вы тоже считаете что обработчик события выполняется в основном потоке?
Спасибо большое, но может посоветуете, как добиться того, чтобы событие обрабатывалось в основном потоке?
...
Рейтинг: 0 / 0
15.08.2013, 14:41
    #38367598
palich12
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Передача данных между потоками
Нашел форум, где тоже обсуждалась аналогичная задача, там есть пара решений, не очень красивые на мой взгляд, но лучше чем ничего. Вот если кому нужно http://www.gotdotnet.ru/forums/3/93216/
...
Рейтинг: 0 / 0
15.08.2013, 19:36
    #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
15.08.2013, 23:08
    #38368280
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Передача данных между потоками
palich12Где-то в степиskole,
так у та и возникли проблемы с ui, или вы тоже считаете что обработчик события выполняется в основном потоке?
Спасибо большое, но может посоветуете, как добиться того, чтобы событие обрабатывалось в основном потоке?
Да никак, Вы инициализируете событие указателем на кусок кода с определенной сигнатурой, которое и исполнится в определенный момент, мало того вы в сигнатуру при вызове тащите this, то есть вы можете из обработчика изменить состояние чего то что породило событие, ( хотя и не следует это делать) , а теперь подумайте как это все хозяйство протащить в основной поток?
следует акцентироваться на своих желаниях, или событие ( в классическом виде) или подать сигнал кому то, что что то произошло в потоке ( костровая почта, маршалинг, меседж, и т.д) и двигать поток дальше.., советую взять тайм аут и вернуться к истокам ( базовым знаниям) подшлифовать их честно скажу - незападло( нем мог подобрать синоним, извините) даже гуру..
...
Рейтинг: 0 / 0
16.08.2013, 06:35
    #38368390
LameUser
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Передача данных между потоками
palich12Нашел форум, где тоже обсуждалась аналогичная задача, там есть пара решений, не очень красивые на мой взгляд, но лучше чем ничего. Вот если кому нужно http://www.gotdotnet.ru/forums/3/93216/

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


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