nemerle: макрос limit_time
От: PhantomIvan  
Дата: 24.09.06 23:09
Оценка:
хотелось мне для синхронного console.readkey() ограничить время его действия
Автор: PhantomIvan
Дата: 23.09.06

чтобы юзер, легший спать, не просыпался каждые 5 минут нажать кнопку
для этого я написал макрос
    public macro limit_time (expression, time, default)
    {
        def invoke =
        <[ {
            mutable result;
            def thread = Thread(() => result = $expression);
            thread.Start();
            if (thread.Join($time))
                result
            else
            {
                thread.Abort();
                //thread.Join();
                $default
            }
        } ]>;
        
        <[ $invoke ]>
    }

на самом деле, для консоли мне там подсказали более правильный вариант
но вдруг кому макрос понадобится
у этого способа есть недостатки: обратите внимание на
                //thread.Join();

у меня с моим вызовом по типу
                def pressed = limit_time (ReadKey(), AutoInterval, ConsoleKeyInfo(Auto, ConsoleKey.A, false, false, false));

плодятся треды в количестве 1 штука на вызов, и я понял почему
thread.Abort() вызывает исключение в треде, и его можно даже обработать
но рантайм пошлет это исключение только после того, как управление вернется из unmanaged-блока, если оно в нем находится
а в console.readkey() по сути вызов к функции winapi, поэтому тред терпеливо ждет нажатия клавиши, и не закрывается даже после аборта
thread.Join, если его раскомментировать, обязательно дождется разрушения потока, но макрос limit_time() (иногда) работать не будет, т.к. когда поток соизволит закрыться — это не определено, и макрос может вместо ограничения времени подвесить программу (что в моем случае и происходило)
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>

30.01.07 18:13: Перенесено модератором из 'Декларативное программирование' — IT
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.