Как мога да събудя спяща нишка в C#?

Преди хората да го предложат: Не използвам Thread.sleep за нищо, освен да се опитвам да намеря начин да го заобиколя. Опитвам се да се справя с бъдещия код на други хора, който може да не е свободен от .Sleep(). Имам много добра представа колко ужасно е синхронизирането на нещата.

Приемам нишка в част от моя код. Искам да мога да задам ограничение за живота на тази тема. Обичайният ми метод за това е следният:

Thread outer = new Thread(() =>
{
    externalThread.Start();
    externalThread.Join();
});
outer.Start();
outer.Join(lifetime);
if (outer.ThreadState != ThreadState.Stopped)
{
    outer.Abort();
}
inner.Join();

Оттогава открих, че очевидно не мога да събудя спяща нишка, преди сънят да приключи. За да влошат нещата, това все още пише в конзолата, ако му дам живот от 10 милисекунди:

new Thread(() => { Thread.Sleep(2000); Console.WriteLine("second"); })

Въпреки че осъзнавам, че .Abort() не е твърдо ограничение за изпълнение на нишка. Изглежда, че 2 секунди биха били достатъчни за предупреждение, но предполагам, че не...

Опитах се да проверя за състоянието на WaitSleepJoin и .Interrupt(); срива нишката или хвърля изключение (съжалявам, не съм сигурен кое. Windows ми казва, че се е сбило, ако не работи дебъгер, а ако работи, работи, сякаш не е извикано прекъсване) и все още пише в конзолата след 2 секунди . .Resume() очевидно не прави нищо на спяща нишка.

Има ли начин да събудите нишка, без да чакате изтичането на режима на заспиване? Разбирам, че спирането не е "незабавно", така че Console.WriteLine може да бъде извикан независимо; изчакването от 2 секунди ме притеснява. Ами ако се чака 10 дни? Тъй като не мога да контролирам нишките, които влизат, няма начин да знам и изглежда няма начин да предотвратя подобно нещо...


person Groxx    schedule 31.12.2010    source източник
comment
Как ще имате препратка към темите на други хора?   -  person Tim Lloyd    schedule 31.12.2010
comment
void myFunc(Thread externalThread){ // прибл. горният код}   -  person Groxx    schedule 31.12.2010
comment
ако чакате 10 дни, кажете на ръководителя си, за да може разработчикът, който е направил това, да бъде уволнен. Не се опитвайте да покриете всички възможни идиотии на некомпетентни разработчици.   -  person John Saunders    schedule 31.12.2010
comment
Наистина не виждам какво се опитвате да приложите от въпроса. Това някакъв диспечер на задачи ли е? Моля за повече подробности.   -  person Tim Lloyd    schedule 31.12.2010
comment
@chibacity: това е половината от дълга задача, изпълняваща част от код, така че мога да стартирам събития на ajax и да проверя техния напредък. Това е всеобхватният мениджърски код.   -  person Groxx    schedule 31.12.2010


Отговори (2)


Не, няма начин да събудите нишка от сън. Можете да прекъснете нишка само чрез извикване на Abort или Interrupt (и двете хвърлят ThreadAbortException).

Но за да ви отговоря на въпроса защо, когато работите:

new Thread(() => { Thread.Sleep(2000); Console.WriteLine("second"); })

с таймаут от 10 ms все още се отпечатва, това е защото вашият код за контролиране на живота на нишката не прави това, което искате да направите.

Така че имате externalThread и outer. Започвате outer (което стартира нова нишка, нека я наречем нишка 1) и от външно извикване start на външна нишка (която стартира нова нишка, нека я наречем нишка 2). Така че току-що започнахте две нови теми.

Когато извикате outer.About(), това прекъсва само нишка 1. Нишката, започната с извикване на externalThread.Start(), нишка 2 продължава да се изпълнява до завършване, тъй като нищо не я прекъсва.

Не съм сигурен какво се опитвате да постигнете с допълнителната външна нишка. Няма ли да е по-просто:

externalThread.Start();
externalThread.Join(lifetime);
if (externalThread.ThreadState != ThreadState.Stopped)
{
    externalThread.Abort();
}
person shf301    schedule 31.12.2010
comment
Би било, ако не раждах куп теми; Имам нужда от програмен начин да ги спра всички. От това и малко експериментиране имах страхотен момент: Прекъсването не се разпространява. По някаква причина си мислех, че нишките по някакъв начин са обхванати от това къде са започнали, но сега разбирам защо това не може да е така. Благодаря за отговора! - person Groxx; 31.12.2010

Използвайте WaitOne + таймер, за да контролирате нишки с неизвестен произход.

или ако имате контрол върху работния код на нишката:

доста хакерски начин, за да постигнете по-„отзивчив сън“, когато не харесвате таймери/други нишки, използвани за събуждане на нишката

използвайте го вместо нормалния Thread.Sleep

    private void WaitFor(int milis)
    {
        const int interval = 500;

        if (milis <= interval)
        {
            throw new ArgumentException();
        }

        var sections = milis / interval;
        for (var s = 0; s < sections && (!ShouldQuit); ++s)
        {
            Thread.Sleep(interval);
        }
    }

забележете флага ShouldQuit, който е поле на клас, достъпно и от двете нишки

разбира се, това има по-лоши характеристики за използване на процесора от изчакване, базирано на събитие/таймер

person Cyryl Płotnicki    schedule 08.12.2011