Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
7 / 7 / 3
Регистрация: 10.04.2015
Сообщений: 57
1

Как десериализовать в отдельном потоке ?

21.10.2016, 20:24. Показов 1402. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Метод MessageReceiverFirst принимает сокет и потом в отдельном потоке десериализует объект который передает этот же клиент. Когда делаю все в главном потоке все работает, как только я выполняю все это в отдельном потоке нечего не выходит глобальная переменная для десериализации всегда null.
Подскажите что я упустил, не могу сообразить...
Метод ацептера:
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
  private void SocketAccepter()
        {
            Thread th = new Thread(delegate ()
            {
                Socket cl;
                Client cli;
                int Cur = 0;
                while (isServerRunning)
                {
                    try
                    {
                        MyMSG += new Action<MessageLib.Message>(MyEvMeth);
                        cl = listener.Accept();
                        isDone = true;
                        //MSGEvent();
                        MessageReceiverFirst(cl);
                        cli = new Client(cl, msg);
 
                      if (MyEvent1 != null)
                        {
                            
                            MyEvent1("\n\r" + "Client connected: ID:" + Cur.ToString() + "\n\r");
                        }
 
                        if (MyEvent != null)
                        {
                            MyEvent(cli);
                        }
}
                    catch (Exception e)
                    {
                        MyEvent1("Exeption: "+e.ToString());
                    }
                }
            });
            th.IsBackground = true;
            th.Start();
        }
Метод приема сообщения для десериализации
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
private void MessageReceiverFirst(Socket r_client)
        {
 
            //Для каждого нового подключения, будет создан свой поток для приема пакетов
            Thread th = new Thread( (object msg) =>
            {
                while (isDone)
                {
                   
                    //if (r_client.Connected)
                    //{
                    // Сюда будем записывать принятые байты
                    byte[] bytes = new byte[1024];
                        // Принимаем 
                        r_client.Receive(bytes);
                        if (bytes.Length != 0)
                        {                        
                        msg = ((MessageLib.Message)Deserialize(bytes));
                        
                    }
                        isDone = false;
                       
                    //}
                }
            Thread e = Thread.CurrentThread;
            e.Abort();
 
        });
          
            th.IsBackground = true;
            th.Start(msg);
        }
Метод десериализации:
C#
1
2
3
4
5
public static object Deserialize(byte[] data)
        {
            using (var memoryStream = new MemoryStream(data))
                return (new BinaryFormatter()).Deserialize(memoryStream);
        }
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.10.2016, 20:24
Ответы с готовыми решениями:

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

Как запустить форму в отдельном потоке
Как запустить форму в отдельный поток.

Как запустить метод в отдельном потоке?
Есть у меня класс и статический метод Class myClass { ... public static void Method1(string...

Как исполнять метод в отдельном потоке?
Как исполнять метод в отдельном потоке? То есть, в процессе работы программы метод вызывается...

10
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
21.10.2016, 21:03 2
Bespredeliwe, как это вообще компилится?
Может через Task всё это осуществить, и чтоб не висло, пока всё это происходит, еще и async?
Сразу бросается в глаза:
C#
1
2
3
4
5
6
         Thread th = new Thread( (object msg) =>
            {
                 // ToDo
            }); //th
            th.IsBackground = true;
            th.Start(msg);// откуда тут msg взялось??????????????
0
7 / 7 / 3
Регистрация: 10.04.2015
Сообщений: 57
21.10.2016, 21:10  [ТС] 3
Тут естественно не весь код, msg это глобальная переменная, куда я записываю десериализырованный объект. По моему разницы с помощью какого класса я буду создавать поток вообще нету, суть в том что в отдельном нечего не десериализуется.
0
Администратор
Эксперт .NET
17553 / 13776 / 5298
Регистрация: 17.03.2014
Сообщений: 28,254
Записей в блоге: 1
21.10.2016, 21:15 4
Bespredeliwe, переменная msg не меняется по той же причине по которой в примере ниже не меняется массив.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
static int[] arr;
static void Main()
{
    arr = new int[]{10,20,30,40};
    Console.WriteLine(arr[0]); // 10
    DoSmth(arr);
    Console.WriteLine(arr[0]); // Все еще 10
}
 
static void DoSmth(object obj)
{
    obj = new int[] {-10,-20,-30,-40};
}
Кликните здесь для просмотра всего текста
Меняется локальная переменная ссылочного типа
0
7 / 7 / 3
Регистрация: 10.04.2015
Сообщений: 57
21.10.2016, 21:29  [ТС] 5
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Bespredeliwe, переменная msg не меняется по той же причине по которой в примере ниже не меняется массив.
Хорошо, если я просто запускаю поток (без параметров) и передаю ему глобальную переменную msg то тоже нечего не происходит, так же и с событиями.
0
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
21.10.2016, 21:31 6
Bespredeliwe, предположим, что наш метод выглядит так:
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
        private void MessageReceiverFirst(Socket r_client)
        {
 
            //Для каждого нового подключения, будет создан свой поток для приема пакетов
            Thread th = new Thread(() =>
            {
                while (isDone)
                {
 
                    //if (r_client.Connected)
                    //{
                    // Сюда будем записывать принятые байты
                    byte[] bytes = new byte[1024];
                    // Принимаем 
                    r_client.Receive(bytes);
                    if (bytes.Length != 0)
                    {
                        this.msg = ((MessageLib.Message)Deserialize(bytes));
 
                    }
                    isDone = false;
 
                    //}
                }
                Thread e = Thread.CurrentThread;
                e.Abort();
 
            });
 
            th.IsBackground = true;
            th.Start(msg);
        }
То как только тут:
C#
1
2
                    //if (r_client.Connected)
                    //{
мы раскомментируем, msg будет каждую итерацию присваиваться новое значение, возможно в этом и есть задумка, выйти из цикла с нужным значением msg.
0
7 / 7 / 3
Регистрация: 10.04.2015
Сообщений: 57
21.10.2016, 21:36  [ТС] 7
Цитата Сообщение от EveKS Посмотреть сообщение
мы раскомментируем, msg будет каждую итерацию присваиваться новое значение, возможно в этом и есть задумка, выйти из цикла с нужным значением msg.
Нету там никакой задумки, это обычное свойство сокета которое я закоментил так как там нету смысла в такой проверке. Просто как бы я не хотел передать значение десериализации главному потоку, оно не передается... Повторюсь, когда запускаю все в одном потоке, все работает как часы.
0
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
21.10.2016, 21:38 8
Bespredeliwe, раз нету смысла в проверке, то зачем цикл с одной итерацией)?
Как метод без Thread выглядит?
0
7 / 7 / 3
Регистрация: 10.04.2015
Сообщений: 57
21.10.2016, 21:45  [ТС] 9
Цитата Сообщение от EveKS Посмотреть сообщение
Bespredeliwe, раз нету смысла в проверке, то зачем цикл с одной итерацией)?
Как метод без Thread выглядит?
Там вместо цикла можно использовать if... пока не суть важно. Общий смысл метода: как только подключатся новый клиент мы создаем поток и в нем сразу же получаем объект (в 1м сообщении на 1024 байта), который десиарелизируем и помещаем в специальный класс с сокетом (для соединения с клиентом) и параметрами которые были получены 1м сообщением. Без Thread метод выглядит так же просто убери лямбду
0
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
21.10.2016, 22:26 10
Лучший ответ Сообщение было отмечено Bespredeliwe как решение

Решение

Bespredeliwe,
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        private async Task MessageReceiverFirst(Socket r_client)
        => await Task.Run(()=>
        {
            if (isDone)
            {
                byte[] bytes = new byte[1024];
 
                r_client.Receive(bytes);
                if (bytes.Length != 0)
                {
                    this.msg = ((MessageLib.Message)Deserialize(bytes));
                }
                isDone = false;
            }
        });
Message msg.

Добавлено через 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
        private async Task SocketAccepter()
        => await Task.Run(async ()=>
        { 
                Socket cl;
                Client cli;
                int Cur = 0;
                while (isServerRunning)
                {
                    try
                    {
                        MyMSG += new Action<MessageLib.Message>(MyEvMeth);
                        cl = listener.Accept();
                        isDone = true;
                        //MSGEvent();
                        await MessageReceiverFirst(cl);
                        cli = new Client(cl, msg);
 
                        MyEvent1?.Invoke("\n\r" + "Client connected: ID:" + Cur + "\n\r");
                        MyEvent?.Invoke(cli);
                    }
                    catch (Exception e)
                    {
                        MyEvent1("Exeption: " + e.ToString());
                    }
                }
            });
Добавлено через 30 минут

Не по теме:

Или мне кажется, или там куча лишних действий.

1
7 / 7 / 3
Регистрация: 10.04.2015
Сообщений: 57
21.10.2016, 22:31  [ТС] 11
EveKS, Спасибо, все работает. Понял в чем была проблема... Поток не успевал отработать и записать в глобальную переменную наш объект, таким образом не дождавшись завершения потока в метод попадал null... С asnyc/await все работает!
0
21.10.2016, 22:31
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.10.2016, 22:31
Помогаю со студенческими работами здесь

Как выполнить функцию в отдельном потоке?
Вызывается функция, которая выполняется достаточно долго. Как вызвать эту функцию в отдельном...

Как запустить async метод в отдельном потоке?
как мне запустить этот метод во вторичном потоке public async Task&lt;List&lt;string&gt;&gt; ApiReq(string...

Как воспроизвести в отдельном потоке данный метод?
public static void WriteX(string fr) { try { ...

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

Как запустит часть кода в отдельном потоке?
Как запустит часть кода в отдельном потоке? Например: как запустить картинку в отдельном потоке? ...

Как запустить определённый код в отдельном потоке по нажатию кнопки?
как запустить определённый код в отдельном потоке по нажатию кнопки?(этот код бесконечен)


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

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