powered by simpleCommunicator - 2.0.54     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Странное поведение потока
25 сообщений из 32, страница 1 из 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
25 сообщений из 32, страница 1 из 2
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Странное поведение потока
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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