#c# #multithreading #entity-framework #stack-overflow
#c# #многопоточность #entity-framework #переполнение стека
Вопрос:
У меня был основной поток, выступающий в качестве диспетчера заданий. Он запрашивает термины из базы данных и отправляет эти термины для асинхронного веб-ввода-вывода. Когда веб-ответ поступает, пул потоков отправляет поток для обработки этого ответа и сохранения в БД.
Исключение StackOverflowException происходит в основном потоке. Которые используют entity framework для получения набора терминов из БД. Код, как показано ниже.
В настоящее время мне интересно следующее: когда я использую метод BeginGetResponse() для создания рабочих элементов для пула потоков, где размещаются рабочие элементы? в стеке основного потока? может ли это быть причиной StackOverflow? Если да, должен ли я замедлить скорость создания рабочих элементов??
Есть ли какой-нибудь способ:
- Определите, какой стек потока переполнен?
-
Каково содержимое переполненного стека?
while(!jobDone) { while(availableBatchQuota<=0) { polling = true; Thread.Sleep(pollingInterval); Console.Write("rPolling..."); } if (polling) { Console.WriteLine(); polling = false; } //At least 1 quota is available if (terms.Any()) <=========StackOverflow exception here! { Interlocked.Decrement(ref availableBatchQuota); SearchTermsDistinct term = terms.Take(1).ToList()[0]; ContextlessTerm term2 = new ContextlessTerm(); term2.Term = term.Term; term2.TermId = term.Term_ID; SearchAsync(term2, 1); terms = terms.Skip(1); } else jobDone = true; }
—
public static void SearchAsync(ContextlessTerm term, Int32 pageIndex)
{
String processedTerm = TermPreProcess.Process(term.Term);
if (processedTerm.Length == 0) return; // if the term is empty, we shouldn't search it.
Console.WriteLine("Searching term: {0}", processedTerm);
String query = String.Format(queryString, processedTerm, (pageIndex - 1) * 10 1);
//Console.WriteLine(query);
WebRequest request = WebRequest.Create(query);
request.Proxy = null;
request.Method = "GET";
request.BeginGetResponse(ar =>
{
List<mySearchResultClass> resultsOnePage = null;
using (WebResponse response = request.EndGetResponse(ar))
{
resultsOnePage = GetResultURLsForOnePage(response.GetResponseStream());
Int32 rank = 1;
foreach (var result in resultsOnePage)
{
result.Rank = (pageIndex - 1) * 10 rank;
rank ;
}
}
lock (dbSync)
{
SaveToDB(term, resultsOnePage);
}
if (pageIndex < maxSearchPages amp;amp; resultsOnePage.Count() == 10) SearchAsync(term, pageIndex 1);// relay race!
else
{
Interlocked.Increment(ref availableBatchQuota);
Interlocked.Increment(ref progress);
//Console.ForegroundColor = ConsoleColor.Cyan;
//Console.WriteLine("Done searching term: {0}", processedTerm);
Console.WriteLine("{0}: Available: {1}tProgress:{2:f3}%", DateTime.Now.ToString(), availableBatchQuota, progress * 100.0 / totalTerms);
//Console.ResetColor();
}
}, null);
}
ДОБАВИТЬ 1
Ниже то, что я вижу в окне DEBUG-> Threads. Похоже, что основной поток попал в беду.
ДОБАВИТЬ 2
Трассировка стека.
ДОБАВИТЬ 3
Я просто повторно запускаю свое приложение, на этот раз исключение происходит в том же месте, но проблемная DLL изменяется на EntityFramework.dll . Слишком странно…
Необработанное исключение типа ‘System.StackOverflowException’ произошло в EntityFramework.dll
Комментарии:
1. Находится
terms
вif (terms.Any())
IEnumerable<>
? Если это так, это может быть побочным эффектом отложенной оценки LINQ. Возможно, вся последовательность подвергается переоценке.
Ответ №1:
Не видя трассировки вашего стека, немного сложно дать окончательный ответ, но я думаю, что соблюдение основ заставляет меня поверить, что источником вашего StackOverflow является
SearchAsync(ContextlessTerm term, Int32 pageIndex)
который вызывает себя:
if (pageIndex < maxSearchPages amp;amp; resultsOnePage.Count() == 10) SearchAsync(term, pageIndex 1);// relay race!
Вы проанализировали свой код, чтобы узнать, насколько глубока ваша рекурсия в среднем? Всегда ли он попадает в StackOverflow или только при определенных обстоятельствах?
Комментарии:
1. Я попытался проверить сведения об исключении при запуске ОТЛАДКИ, но там просто написано «Невозможно вычислить выражение, поскольку текущий поток находится в состоянии переполнения стека».
2. Было бы полезно узнать, на каком языке программирования это. Похоже на C #?
3. Да, C #. Кроме того, я установил условие для рекурсии, маловероятно, что бесконечная рекурсия.
4. @smwikипедия: не сведения об исключении, требуется трассировка стека. Просто покажите содержимое окна stack debugger.
5. @PMF Я добавил трассировку стека к своему вопросу. Но это кажется не очень полезным.