‘Система.StackOverflowException’ произошло в mscorlib.dll ?

#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 Я добавил трассировку стека к своему вопросу. Но это кажется не очень полезным.