В настоящее время я пишу интерфейс на основе веб-служб в существующее приложение.Для этого я использую WCF LOB Adapter SDK , который позволяет создавать пользовательские привязки WCF, которые предоставляют внешние данные и операции в виде веб-служб.
SDK предоставляет несколько интерфейсовдля реализации, и некоторые из их методов ограничены во времени: ожидается, что реализация завершит свою работу в течение указанного промежутка времени или выдаст TimeoutException .
Под руководством расследованиямне на вопрос " Реализация общего тайм-аута C # ", который мудро советует использовать рабочий поток.Вооружившись этим знанием, я могу написать:
public MetadataRetrievalNode[] Browse(string nodeId, int childStartIndex,
int maxChildNodes, TimeSpan timeout)
{
Func<MetadataRetrievalNode[]> work = () => {
// Return computed metadata...
};
IAsyncResult result = work.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeout)) {
return work.EndInvoke(result);
} else {
throw new TimeoutException();
}
}
Однако, консенсус не ясен относительно того, что делать с рабочим потоком, если он истекает.Можно просто забыть об этом, как это делает приведенный выше код, или можно прервать его:
public MetadataRetrievalNode[] Browse(string nodeId, int childStartIndex,
int maxChildNodes, TimeSpan timeout)
{
Thread workerThread = null;
Func<MetadataRetrievalNode[]> work = () => {
workerThread = Thread.CurrentThread;
// Return computed metadata...
};
IAsyncResult result = work.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeout)) {
return work.EndInvoke(result);
} else {
workerThread.Abort();
throw new TimeoutException();
}
}
Теперь прерывание потока обычно считается неправильным .Он прерывает текущую работу, теряет ресурсы, портит блокировку и даже не гарантирует, что поток действительно прекратит работу.Тем не менее, HttpResponse.Redirect()
прерывает поток каждый раз, когда он вызывается, и IIS, кажется, вполне доволен этим.Может быть, он готов как-то с этим справиться.Мое внешнее приложение, вероятно, не является.
С другой стороны, если я позволю рабочему потоку запустить свой курс, кроме увеличения конкуренции за ресурсы (меньше доступных потоков в пуле), не будет утечка памятив любом случае, потому что work.EndInvoke()
никогда не вызывается?Точнее говоря, не будет ли массив MetadataRetrievalNode[]
, возвращаемый work
, навсегда остаться?
Это только вопрос выбора меньшего из двух зол, или есть способ не прервать рабочий потоки до сих пор вернуть память, используемую BeginInvoke()
?