powered by simpleCommunicator - 2.0.54     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Странное поведение потока
32 сообщений из 32, показаны все 2 страниц
Странное поведение потока
    #38960361
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Какая-то непонятная ерунда творится. Есть небольшое WPF приложение. В нем создан поток со следующим кодом (см. ниже). В коде всю полезную работу закомментировал, но задержка на точке останова большая. Причем, иногда я запускаю приложения и все летает (то есть каждую секунду попадаем на строчку future_dt = cur_dt.AddSeconds(1)), а иногда какая-то засада случается на Thread.Sleep. Запускаю непосредственно из VS 2010. Я не специалист в C#, поэтому не понимаю с чем это может быть связано. Думал, может GC включается в работу, но даже перегружал комп - не помогло. Посидел, попил чаек, через час подхожу - все летает. На следующий день - опять тормоза

Код: 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.
      
        int delta_ms = 1;

        thread = new Thread(OnThreadStart);
        thread.Start();

        void OnThreadStart()
        {
            while (!is_stop)
            {
                if (cur_dt >= future_dt || future_dt == null)
                {
                    // ... полезная работа

                    // здесь я ставлю точку останова и ожидаю попадать в нее примерно каждую секунду,
                    // но в действительности попадаю примерно 1 раз в 15-30 секунд
                    future_dt = cur_dt.AddSeconds(1);        
                }

                cur_dt = cur_dt.AddMilliseconds(delta_ms);

                // ... полезная работа

                Thread.Sleep(interval_ms);          // почему-то тут спим не 1 мс, а существенно дольше 
            }
        }
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960364
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Перед тем как начал писать, были торомоза. Запустил спустя 5 минут все летает. Подозреваю, что GC это. Как бороться?!
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960393
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если есть Task'и нафига использовать Thread?
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960409
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
myaucha
Код: c#
1.
Thread.Sleep(interval_ms);          // почему-то тут спим не 1 мс, а существенно дольше


Минимальный интервал времени для данного метода не менее 10 миллисекунд. Обычно - 15 мс. Реально - больше.
К тому же, это лишь намёк потоку, что пора бы проснуться, а если у ОС есть другие дела, то поток может спать ещё долго.
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960480
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvikМинимальный интервал времени для данного метода не менее 10 миллисекунд. Обычно - 15 мс. Реально - больше.
К тому же, это лишь намёк потоку, что пора бы проснуться, а если у ОС есть другие дела, то поток может спать ещё долго.Если минимальный интервал 10-15 мс, то каким образом приведенный код работает иногда без задержек (как положено - какжую секунду), а иногда сильно подвисает (жду по 30 секунд). Ведь если бы интервал был 10-15 мс, то подвисание было бы постоянным. В период подвисания я смотрел диспетчер задач - активность снижается практически до нуля. Более того, я открывал еще один экземпляр VS и писал код аналогичный следующему
foreach (int i = 0; i<1000; i++) Thread.Sleep(1)
и он отрабатывал за секунду, хотя в первом экземпляре наблюдались тормоза.
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960488
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Имелось в виду...
for (int i = 0; i<1000; i++) Thread.Sleep(1)
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960501
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может быть есть более стабильный способ реализации следующей логики. Есть последовательно технических событий, которые сохранены в виде журнала с указанием времени с точностью до 1 мсек. Мне необходимо воспроизвести эти события во времени. Если Thread.Sleep не является надежным механизмом, то какой механизм следует использовать в качестве альтернативы?!
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960512
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
myauchaЕсть последовательно технических событий, которые сохранены в виде журнала с указанием времени с точностью до 1 мсек. Мне необходимо воспроизвести эти события во времени.

С точностью до 1 мсек? Забей
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960522
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pallaris,

в гугл. Системы Реального Времени
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960531
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman MejtesPallaris,

в гугл. Системы Реального Времени

Winforms .NET? Забей
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960557
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще-то, все это я делаю в WPF. Может он свой отпечаток накладывает?!
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960561
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
myauchaВообще-то, все это я делаю в WPF. Может он свой отпечаток накладывает?!

Thread.Sleep гарантирует, что поток уснет на период, не меньший, чем ты указал. Но он не гарантирует, что поток проснется немедленно после указанного периода
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960573
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
myauchaя ... писал код аналогичный следующему
for (int i = 0; i<1000; i++) Thread.Sleep(1)
и он отрабатывал за секунду
Брехня.
Если только кто-то не пошаманил с функцией timeBeginPeriod. тынц

И вообще, в приличном обществе за использование Thread.Sleep бьют ногами.

ЗЫ: хотелось бы видеть, как объявлена is_stop.
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960580
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvikmyauchaя ... писал код аналогичный следующему
for (int i = 0; i<1000; i++) Thread.Sleep(1)
и он отрабатывал за секунду
Брехня.У меня работает, по крайней мере на Win 7, Core 2 Duo 2GHz, ОЗУ 3Г, 64-разрядная ОС. Ну не выкладывать же видео в самом деле! Придется верить на слово


petalvikЕсли только кто-то не пошаманил с функцией timeBeginPeriod. тынц Нет

petalvikИ вообще, в приличном обществе за использование Thread.Sleep бьют ногами.Предложите альтернативу

petalvikЗЫ: хотелось бы видеть, как объявлена is_stop.Да обычный bool. Он на всем протяжении работы остается false и переключаю я ее только когда собираюсь выходить из приложения, так что она тут не при чем
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960584
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PallarisThread.Sleep гарантирует, что поток уснет на период, не меньший, чем ты указал. Но он не гарантирует, что поток проснется немедленно после указанного периодаЭто я понимаю, но на практике сейчас вижу, что цикл в 1000 итераций со слипом в 1 занимает примерно секунду.

Чем-нибудь принципиально отличается

this.Dispatcher.Invoke((ThreadStart)delegate() { this.Title = date_time.ToString(); });

от

this.Dispatcher.Invoke(new Action(() => this.Title = date_time.ToString()));

?
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960597
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
myauchaВообще-то, все это я делаю в WPF. Может он свой отпечаток накладывает?!
вообще то, это раздел WF, но сути дела это не меняет. ОС Windows, это не система реального времени, если вам нужен немедленный отклик то выбор явно неудачный.
Со времен FW.NET 2.0 появилась TPL и использовать Thread, не слишком хорошая идея.
В Task'ах, есть специальный метод Wait(ms, cancellationtoken), если потребуется прервать таск в тот момент, когда он ожидает (простаивает).
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960601
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
myauchaУ меня работает,
Ну не выкладывать же видео в самом деле!
Вот этот код что выдаст:
Код: c#
1.
2.
3.
Console.WriteLine(DateTime.Now);
for (int i = 0; i < 1000; i++) Thread.Sleep(1);
Console.WriteLine(DateTime.Now);




myauchaПредложите альтернативуSystem.Timers.Timer.


myauchaДа обычный bool.Мои мрачные предчувствия оправдались. Код на помоечку, автора сжечь (можно наоборот).
На эту тему сломано много копий. Гуглить, например, volatile.
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960602
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtesвообще то, это раздел WF, но сути дела это не меняет. ОС Windows, это не система реального времени, если вам нужен немедленный отклик то выбор явно неудачный.

Roman MejtesСо времен FW.NET 2.0 появилась TPL и использовать Thread, не слишком хорошая идея.Если появилась новая функциональность, то это не аргумент, что старая перестала работать.

Roman MejtesВ Task'ах, есть специальный метод Wait(ms, cancellationtoken), если потребуется прервать таск в тот момент, когда он ожидает (простаивает).И чем этот Wait лучше Sleep-а?!
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960627
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
myaucha,

тем, что в качестве аргумента он принимает CancellationToken и может быть прерван по требованию.
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960638
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvikВот этот код что выдаст:
Код: c#
1.
2.
3.
Console.WriteLine(DateTime.Now);
for (int i = 0; i < 1000; i++) Thread.Sleep(1);
Console.WriteLine(DateTime.Now);



Вот результат

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
            DateTime[] dt = new DateTime[10];

            for (int j = 0; j < 10; j++)
            {
                dt[j] = DateTime.Now;
                for (int i = 0; i < 1000; i++) Thread.Sleep(1);
            }

            for (int j = 0; j < 10; j++)
                Console.WriteLine(dt[j].ToString("dd.MM.yyyy HH:mm:ss.fff"));

16.05.2015 18:33:53.816
16.05.2015 18:33:54.842
16.05.2015 18:33:55.842
16.05.2015 18:33:56.842
16.05.2015 18:33:57.843
16.05.2015 18:33:58.843
16.05.2015 18:33:59.843
16.05.2015 18:34:00.843
16.05.2015 18:34:01.843
16.05.2015 18:34:02.850



petalvikmyauchaПредложите альтернативуSystem.Timers.Timer.Это не альтернатива, а масло масленное


petalvikmyauchaДа обычный bool.Мои мрачные предчувствия оправдались. Код на помоечку, автора сжечь (можно наоборот). На эту тему сломано много копий. Гуглить, например, volatile.Вы вообще читаете, что вам отвечают?! Я же написал, что переменная не меняется - она на всем протяжении жизни потока всегда содержит значение false и не оказывает никакого влияния на задержку
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960663
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtesmyaucha,
тем, что в качестве аргумента он принимает CancellationToken и может быть прерван по требованию.Я из главного WPF потока создаю дочерний, который циклически по времени читает технические события из файла и отображает их посредством Dispatcher.Invoke в главном окне. Что вы мне рекомендуете прервать в нужны момент?!
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960675
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
myauchaВот результат
<skip>
А вот мой результат вашего кода:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
16.05.2015 20:39:01.751
16.05.2015 20:39:17.376
16.05.2015 20:39:33.001
16.05.2015 20:39:48.626
16.05.2015 20:40:04.251
16.05.2015 20:40:19.876
16.05.2015 20:40:35.501
16.05.2015 20:40:51.127
16.05.2015 20:41:06.923
16.05.2015 20:41:23.095


Причина - кто-то или что-то пошаманил с функцией timeBeginPeriod.
В WPF значение интервала системного таймера меняются. Почему не стоит разгонять таймер Windows . То есть предугадать продолжительность тика таймера невозможно (если не задавать её самому).


myauchapetalvikSystem.Timers.Timer.Это не альтернатива, а масло масленное
Это разумная альтернатива. При вызове Thread.Sleep поток спит, продолжая при этом потреблять системные ресурсы (отнимая мегабайт памяти (пусть и виртуальной), заставляя диспетчер потоков обслуживать себя). В то время как Timer один на всю систему, запросы к нему выстраиваются в очередь, и добавление вашего не загрузит систему лишней работой.
Длина тика при этом - смотрите выше ссылку.


myauchaВы вообще читаете, что вам отвечают?! Я же написал, что переменная не меняется - она на всем протяжении жизни потока всегда содержит значение false и не оказывает никакого влияния на задержку
Повторяю: гуглить volatile. Компилятор может выбросить цикл вообще, видя, что переменная не меняется. Он знать не знает, что там происходит в других потоках. В данном конкретном случае такой код может работать, в другом (с другой версией фреймворка/CLR, с другим компилятором) - может не работать.
Это очень распространённая ошибка. Было время, я сам писал многопоточный код с обычными булевыми флагами. И он даже работал (иногда). А иногда ломался. Именно поэтому разработчиками дотнета был введён CancellationToken, который является потокобезопасным.
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960681
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
myaucha,

если вы тупо читаете из файла, тогда нафига всё это?
откройте файл на чтение и читайте в цикле, если достигли конца потока, то делайте паузу, проверяйте опять на конец потока и если новые данные в файле появятся, то читайте дальше... нафига городить для этого таймер?
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960683
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
так же есть SystemFileWatcher который может возбуждать событие, если файл был изменён.
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960706
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А такой результат что выдаст?
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
            DateTime[] dt = new DateTime[10];

            for (int j = 0; j < 10; j++)
            {
                dt[j] = DateTime.Now;
                for (int i = 0; i < 1000; i++) Thread.CurrentThread.Join(1);
            }

            for (int j = 0; j < 10; j++)
                Console.WriteLine(dt[j].ToString("dd.MM.yyyy HH:mm:ss.fff"));




Это разумная альтернатива. При вызове Thread.Sleep поток спит, продолжая при этом потреблять системные ресурсы (отнимая мегабайт памяти (пусть и виртуальной), заставляя диспетчер потоков обслуживать себя). В то время как Timer один на всю систему, запросы к нему выстраиваются в очередь, и добавление вашего не загрузит систему лишней работой.
Длина тика при этом - смотрите выше ссылку.У меня поток при слипе не ест процессорное время (про память не знаю, но 1Мб памяти не критично), а вот системный таймер не укладывается в 1 мс

Повторяю: гуглить volatile. Компилятор может выбросить цикл вообще, видя, что переменная не меняется. Он знать не знает, что там происходит в других потоках. В данном конкретном случае такой код может работать, в другом (с другой версией фреймворка/CLR, с другим компилятором) - может не работать.
Это очень распространённая ошибка. Было время, я сам писал многопоточный код с обычными булевыми флагами. И он даже работал (иногда). А иногда ломался. Именно поэтому разработчиками дотнета был введён CancellationToken, который является потокобезопасным.Сделать отдельные переменные потокобезопасными можно и другими способами, но сейчас вопрос заключается не в этом

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

Thread.Sleep гарантирует, что поток уснет на период, не меньший, чем ты указал. Но он не гарантирует, что поток проснется немедленно после указанного периода

Не видел в разьяснениях про квант времени -
Виндовс не реал тайм система, потому, что всем запущеным потокам выдает по 15 милисекунд на поработать.
Потом отдает время следующему потоку.
Если система не занята, то высока вероятность, что следующий поток это будет тот же самый.
Thread.Sleep(0) отпускает квант, и время передается другому потоку. Thread.Sleep(0) == Thread.Sleep(15) по функциональности.

По поводу реал-тайм систем - на дотнете их делать можно, но при помощи негативной логики -
вы должны писать проверку в цикле, выполнение какого-нибудь условия на внешнем устройстве (установленный бит или типа того), и только после этого давать следующую команду.

Быть уверенным в интервалах нельзя.
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960765
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
myauchaНе тупо читаю, а с привязкой ко времени. Файл сформирован и зафиксирован, новые данные в него не поступают. А если быть точным, то файлов несколько и в каждом свои технические события со временем возникновения. Я, по сути, их просто проигрываю

Roman Mejtesтак же есть SystemFileWatcher который может возбуждать событие, если файл был изменён.
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960772
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cat2myauchaНе тупо читаю, а с привязкой ко времени. Файл сформирован и зафиксирован, новые данные в него не поступают. А если быть точным, то файлов несколько и в каждом свои технические события со временем возникновения. Я, по сути, их просто проигрываю

Roman Mejtesтак же есть SystemFileWatcher который может возбуждать событие, если файл был изменён.

И к чему это?!
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960789
myaucha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvikmyauchaя ... писал код аналогичный следующему
for (int i = 0; i<1000; i++) Thread.Sleep(1)
и он отрабатывал за секунду
Брехня.
Если только кто-то не пошаманил с функцией timeBeginPeriod. тынц В общем, путем нехитрых экспериментов (проверил практически все, что мне тут посоветовали) самым стабильным решением оказалось применение такой вот конструкции

TimeBeginPeriod(1);
Thread.Sleep(1);
TimeEndPeriod(1);

За ссылку отдельное спасибо petalvik-у. Без TimeBeginPeriod у меня тоже работало, но только при запущенном браузере Chrome. Закрываешь хром - Sleep виснет. Но! Даже при закрытом хроме, если в WPF приложении нажать на кнопку (просто обычный Button, помещенный на форму без всякой логики), то Sleep тоже начинает работать стабильно. Видимо WPF и хром у себя где-то используют TimeBeginPeriod тоже.

Кстати, читал попутно, что Thread.Sleep(0) тождественно Thread.Sleep(15). У меня при замерах Thread.Sleep(0), в большинстве случаев, вообще отрабатывал без задержки, то есть цикл с 1000 итераций и Sleep(0) занимал 0 мсек вне зависимости от того запущен браузер или нет, есть WPF или нет.
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960824
Фотография D129
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
myauchaКстати, читал попутно, что Thread.Sleep(0) тождественно Thread.Sleep(15). У меня при замерах Thread.Sleep(0), в большинстве случаев, вообще отрабатывал без задержки, то есть цикл с 1000 итераций и Sleep(0) занимал 0 мсек вне зависимости от того запущен браузер или нет, есть WPF или нет.
И о чем это говорит, по вашему? Вероятность. Если даже отдали квант в середине цикла - вы этого не заметите.
Просто имейте в виду, что ваша программа идет вперед маленькими кусочками.
О моменте перерыва она не знает.

Хотите замерять точнее - надо использовать Stopwatch.
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960855
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я вот ещё что хочу сказать.
Если нужно выполнять некое действие тысячу раз в секунду (в среднем один раз в одну миллисекунду), то можно поступать так, как делают в играх для программирования плавного движения. Засекаем время входа при начале очередной итерации цикла, выполняем действие. При следующей итерации сравниваем текущее время с запомненным: если прошла всего одна миллисекунда - выполняем наше действие один раз. Прошло 50 мс - выполняем действие 50 раз.
Таким образом можно добиться выполнения действия нужное количество раз. Однако интервалы между ними будут разными.
...
Рейтинг: 0 / 0
Странное поведение потока
    #38960873
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvikЗасекаем время входа при начале очередной итерации цикла, выполняем действие. При следующей итерации сравниваем текущее время с запомненным: если прошла всего одна миллисекунда - выполняем наше действие один раз. Прошло 50 мс - выполняем действие 50 раз..

Дифференцирование для чайников :)
...
Рейтинг: 0 / 0
32 сообщений из 32, показаны все 2 страниц
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Странное поведение потока
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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