2016-04-07 4 views
4

У нас есть служба Windows, которая вызывает сторонний метод, который может висеть при неправильной настройке конечного пользователя, который трудно проверить заранее. Мы обращение с этим риском путем вызова метода в задаче с тайм-аутом:Как я могу отменить зависающую задачу?

private int? FooWithTimeout() 
{ 
    var timeout = TimeSpan.FromMinutes(1); 
    var task = Task.Run(Foo); 

    if (!task.Wait(timeout)) 
    { 
     Log("Foo timed out..."); 
     return null; 
    } 

    if (task.IsFaulted) 
    { 
     Log("Foo threw an exception..."); 
     return null; 
    } 

    return task.Result; 
} 

3-я блокирует метод партии навсегда ожидаем ввод от ресурса, который не может ответить. Это не аннулирование поддержки в любом случае, форме или форме, а также не имеет встроенного тайм-аута. Наша забота заключается в том, что по мере того, как служба запускает эти задачи, она будет продолжать блокировать и медленно накапливаться, в конечном итоге потребляя большой объем ресурсов.

Является ли это действительной проблемой? Нужно ли нам каким-то образом прервать/распоряжаться задачами? Если да, то каков правильный способ сделать это?

Приложение: Третья сторона - это Crystal Reports. Он зависает, когда его просят распечатать на принтер, для которого требуется какой-то дополнительный ввод от пользователя (например, Microsoft XPS Document Writer предложит вам, где сохранить файл, если вы его распечатаете). И, зависаясь, я имею в виду, что он пытается показать приглашение пользователя для получения дополнительного ввода, но он находится в службе Windows, поэтому никто никогда не видит приглашения пользователя, и он всегда ждет, когда человек скажет ему, как печатать. Мы разрешаем конечным пользователям настраивать принтер, к которому пытается выполнить печать служба, и нет никакого способа определить, требует ли данный принтер дополнительного ввода, не пытаясь его распечатать.

+0

что такое 'Foo'? обычный метод, который блокирует поток? Это может помочь, если вам нужно прервать задачу: http://stackoverflow.com/a/19311606/1657476 –

+3

Ваш вопрос в основном «Я взял зависимость от плохо реализованного, случайно зависающего стороннего программного обеспечения, что мне делать? " Мне кажется, что проблему нужно решить, не делая этого в первую очередь *. Если ваша сторонняя сторона делает плохую работу по решению проблемы, попросите их исправить их плохой дизайн или найти альтернативу. Опасные обходные пути, такие как убийство нитей, похоже, решают проблему слишком поздно. –

+0

О, - общий! Я сделал много DLL, которое показывает некоторые подсказки интерфейса. Конечно, это должно быть в конечном итоге исправлено, но у меня не всегда есть время, чтобы сделать правильное решение. Тогда все идет - взлом реестра, временные файлы, партии и так далее. Это не «плохой дизайн», а просто ошибка, которая должна быть исправлена. Трудно найти все приглашения в пользовательском интерфейсе, когда ваше приложение является сложным. – TarmoPikaro

ответ

3

Наша задача в том, что, как работает служба эти задачи будут продолжать блокирование и медленно накапливают

Это действительный интерес. Вы можете уменьшить последствия этого, запустив эти задачи в специальном пуле потоков, который использует небольшие стеки. Таким образом, использование памяти меньше. Но это не полное решение. Если приложение должно функционировать в течение длительного времени (а не графическое приложение, предназначенное для нескольких часов использования), то это решение окажется неприемлемым, поскольку в конечном итоге приложение будет страдать от исчерпания ресурсов.

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

Использование AppDomains может быть безопасным, но это менее очевидно. Возможно, что состояние каждого процесса повреждается, когда AppDomain и потоки в нем прерываются. Кроме того, не все нитки могут быть прерваны. В частности, операции ввода-вывода.

Использование отдельных процессов также не является гарантией того, что из-за прекращения не произойдет никакого государственного повреждения. Но на практике большинство коррумпированных государств живут в памяти. Окончание процесса, вероятно, устраняет все несогласованные состояния.

+0

Существует thread.abort, который также используется iis. И iis работает несколько недель или месяцев. – riki

+1

IIS использует Thread.Abort только для потока * current * в четко определенной точке. Thread.Abort известен как «злой», он не может быть использован. – usr

0

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

Перечислите окна:

How to enumerate all windows belonging to a particular process using .NET?

И близко не хотел окна:

How to use WM_Close in C#?

Может быть, не будет работать, только предложение ...:-)

Смежные вопросы