powered by simpleCommunicator - 2.0.54     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Синхронизация потоков
15 сообщений из 15, страница 1 из 1
Синхронизация потоков
    #38964193
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день!

У меня есть SerialPort. Я подписался на его событие DataReceived
Код: c#
1.
2.
3.
4.
5.
6.
            Port = new SerialPort("COM" + _com_port);
            Port.ReceivedBytesThreshold = Parser.PackageSize+5;
            Port.BaudRate = 9600;
            Port.StopBits = StopBits.One;
            Port.Parity = Parity.None;
            Port.DataReceived += OnPortInput;



Как говорит MSDN при каждом срабатывании DataReceived создаётся отдельный поток (ошибаюсь?).
Что у меня происходит в DataReceived:
Код: 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 OnPortInput(object _sender, SerialDataReceivedEventArgs _e)
        {
            var port = _sender as SerialPort;
            if (port != null)
            {
                string inp = port.ReadExisting();
                Parser.Input = inp;
            }
        }

        public string Input//__property AnsiString Input = { read = FInput, write = SetInput };
        {
            get { return FInput; }
            set { SetInput(value); }
        }

   protected void SetInput(string Value)
        {
            if (string.IsNullOrEmpty(Value))
                return;

            // Дополняем входные данные вновь поступившими
            FInput += Value;

И пошёл всякий код...
        }



Как видите у меня используется одна переменная FInput.
Проблема:
- Вошёл в метод SetInput, иду по коду в режиме отладки;
- Стою на строке 1;
- В строке 1 не происходит ничего серьёзного - просто запись в лог;
- Смотрю что в переменной FInput - данные есть;
- Выполняю строку кода 1 и перехожу на строку 2 (номера условны само собой);
- Смотрю что в переменной FInput - данных нет!

Я так понял что они "съедаются" другим потоком (а метод SetInput может при опр. обстоятельствах скушать данные в FInput), который заработал за спиной моего текущего потока. И дейтсвительно! обратил внимание н апотоки и увидел что пападаю в SetInput в разных потоках параллельно.

Вопрос: Посоветуйте, пожалуйста, как правильно синхронизировать такие потоки? Я их не порождаю ведь! Какие методы/приёмы синхронизации надо применить в данном случае?
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38964204
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ку.,

Прошу прозения. надо уточнить следующее:
В методе SetInput происходит вызов метода Find()
Код: c#
1.
PackageLength = Find(ref FInput);


куда яи передаю по ссылке FInput. именно метод Find и может обрезать строку.
Именно в метод Find я попаадаю из разных потоков и именно внутри него происходит история, когда переходишь на след строку, а в переменно уже пустота!
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38964267
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
дело в том, что хоть string И является классом но, при конкатенации строк, в памяти создается новый объект, куда копируется левый и правый операнд.
то есть вы передаете указатель на объект в памяти, а потом создаете уже новый объект с другим адресом в котором объединяете старую часть и новую :).
думаю проблема именно в этом.
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38964278
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtes,

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

Как можно это проанализировать?
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38964287
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я убрал лишний код в методе SetInput(а именно те части, которые могли обрезать строку). Теперь он такой:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
      protected void SetInput(string Value)//void virtual __fastcall SetInput(AnsiString Value);
        {
            lock (FInput)
            {
                if (string.IsNullOrEmpty(Value)) //if (Value.IsEmpty())
                    return; //    return;

                // Дополняем входные данные вновь поступившими
                FInput += Value;
                DoLog(S_SetInput, FInput); //DoLog(S_SetInput, ARRAYOFCONST((BufferToStr(FInput))));
                return;
}



Стою в режиме отладки на строке DoLog. Перехожу на след и у меня уже пустая строка!
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38964294
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я бы использовал byte[] в качестве хранилища входного буфера, который должен дополняться в процессе и который нужно анализировать. Со строками будут большие проблемы
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38964308
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ку.Roman Mejtes,

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

Как можно это проанализировать?

Код: 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.
    public static class Program
    {

        [StructLayout(LayoutKind.Explicit)]
        public struct SafePtr
        {
            // (1)
            public class ReferenceType
            {
                public object Reference;
            }

            // (2)
            public class IntPtrWrapper
            {
                public IntPtr IntPtr;
            }

            // (3)
            [FieldOffset(0)]
            private ReferenceType Obj;

            // (4)
            [FieldOffset(0)]
            private IntPtrWrapper Pointer;

            public static SafePtr Create(object obj)
            {
                return new SafePtr { Obj = new ReferenceType { Reference = obj } };
            }

            public static SafePtr Create(IntPtr rIntPtr)
            {
                return new SafePtr { Pointer = new IntPtrWrapper { IntPtr = rIntPtr } };
            }

            // (5)
            public IntPtr IntPtr
            {
                get { return Pointer.IntPtr; }
                set { Pointer.IntPtr = value; }
            }

            // (6)
            public Object Object
            {
                get { return Obj.Reference; }
                set { Obj.Reference = value; }
            }

            public void SetPointer(SafePtr another)
            {
                Pointer.IntPtr = another.Pointer.IntPtr;
            }
        }

        static void Main(string[] args)
        {

            var str1 = "Roman ";
            var safeptr1 = SafePtr.Create(str1);
            Console.WriteLine("{0} = {1}", str1, safeptr1.IntPtr.ToInt32());
            var str2 = "Mejtes";
            str1 += str2;
            var safeptr2 = SafePtr.Create(str1);
            Console.WriteLine("{0} = {1}", str1, safeptr2.IntPtr.ToInt32());
            Console.ReadKey();
        }

    }
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38964354
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Отбой!

Проблема найдена. Кое-где в анналах кода была строка которая делала FInput = "";
Проблема обнаружена - чудес не бывает.
Видимо грешить на та что сбивается указатель - неверно. Хотя всё равно было интересно про это узнать. Сейчас всё равно поиграю с указателями.

Вопрос теперь другой возник:
Если я делаю в начале метода lock(FInput) - почему он не срабатывает и позволяет из другого потока сделать FInput = ""?
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38964393
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ку.Если я делаю в начале метода lock(FInput) - почему он не срабатывает и позволяет из другого потока сделать FInput = ""?

Если FInput - строка, то после всяких конкатенаций и Finput="" рассчитывать на то, что в разных потоках lock(FInput) сработает, не стоит. Для лока обычно создают отдельный объект синхронизации
Код: c#
1.
object syncRoot = new object();
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38964398
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pallaris,

Получается, что lock не гарантирует что другая часть кода не получит доступа к объекту синхронизации, а гарантирует то, что одна часть кода, в которой используется lock, не будет выполнена в один момент времени?
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38964495
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ку.Получается, что lock не гарантирует что другая часть кода не получит доступа к объекту синхронизации

Гарантирует, если в другой части кода тоже стоит lock на тот же самый объект.
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38964497
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Фишка в том, что после каждого нового присваивания твой string FInput будет ссылаться на новый объект в памяти, и поэтому использовать его для лока нельзя
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38964507
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pallaris,

О как... Спасибо! Буду дальше изучать тонкости поведения кода! Спасибо всем за ответы/советы!
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38964518
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ку.,

просто создайте flag любую переменную и делайте lock на неё вот и всё
...
Рейтинг: 0 / 0
Синхронизация потоков
    #38965139
ProBiotek
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ку.,

Рассмотрите еще вот эту штуку ReaderWriterLockSlim

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


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