Поток также выполняется после исключения (во время отладки) - PullRequest
0 голосов
/ 04 мая 2011

Я пытаюсь добавить некоторые значения в ArrayList в одном потоке и удалить из другого потока без использования блокировки или мьютекса.При удалении IndexOutOfRangeException выбрасывается и removeThread должен останавливаться только на этом, но это не так!Почему? `

Пожалуйста, посмотрите на следующий код:

class Program
{
    static ArrayList alist = new ArrayList();

    static void Main(string[] args)
    {
        Program p = new Program();
        Thread removeThread = new Thread(p.StartRemoval);
        Thread addThread = new Thread(p.StartAddition);
        addThread.Start();
        removeThread.Start();

        addThread .Join();
        removeThread.Join();

        //Console.ReadKey();
    }

    void StartRemoval()
    {
        for (int i = 0; i < 100000; i++)
            alist.Remove(i); // Exception
    }

    void StartAddition()
    {
        for (int i = 0; i < 100000; i++)
            alist.Add(i); 
    }
}

Даже после исключения в removeThread, он выполняется для оставшихся итераций.Не могли бы вы объяснить, почему?

Трассировка стека:

at System.Collections.ArrayList.RemoveAt(Int32 index) at ConsoleApplication2.Program.StartRemoval() in Program.cs:line 34 at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()

в следующем сценарии, я получаю выше трассировки стека

  1. поставить точку останова на последнюю фигурную скобку всех методов.(main, StartAddition, StartRemoval)

  2. Начать отладку.

  3. StartRemoval выполняет последнюю строку даже после исключения.

Если вы запустите его без отладки, он будет работать правильно и корректно.Но трассировка стека такая же.Remove вызывается в коде, но RemoveAt отслеживается в отчете трассировки.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 04 мая 2011

Не выдает исключение ArrayList.Remove просто выбрасывает NotSupportedException и только когда

The ArrayList is read-only.

-or-

The ArrayList has a fixed size. 

См. Ссылку на MSDN для подробной информации, ваш текущий код неничего не делать, чтобы вызвать исключение.

1 голос
/ 05 мая 2011

Проблема, которую вы видите с исключением во время отладки, вероятно, является результатом того, что код не синхронизирован с двоичными файлами. Я вижу это время от времени. Это случается не очень часто, но я подозреваю, что многие из нас видели, по крайней мере, один или два раза за эти годы. Решение, которое обычно работает, состоит в том, чтобы выбрать Rebuild Solution из пункта меню Build.

Также обратите внимание, что поведение этого кода в целом будет непредсказуемым, поскольку вы обращаетесь к объекту (а именно к экземпляру ArrayList) из более чем одного потока, когда в документации говорится, что экземпляры этого типа не являются потоковыми. сейф.

0 голосов
/ 04 мая 2011

Проблема возникает из-за того, что поток t1 зависит от потока t2, а не наоборот.Поток t2 может успешно добавлять элементы в конец списка массивов, не беспокоясь о том, что находится внутри контейнера (при условии, что ArrayList был правильно распределен, как вы это сделали).

Тем не менее, поток t1 зависит от того, что делает поток t2.Например, поток t1 хочет удалить элемент 5 из alist, его возможный поток t2 все еще добавляет '5', и он еще не существует в alist, тогда это вызывает исключение.Затем t1 выдает это исключение и завершает выполнение.Поскольку t2 не зависит от t1 (как описано выше), оно продолжает выполняться до тех пор, пока не будут добавлены все элементы.

Я полагаю, что следующие проблемы обойдут эту проблему:

t2.Start();    // Start t2 thread
t2.Join();     // Wait for thread t2 to add all elements to alist

t1.Start();    // Start t1 thread knowing all elements in alist have been added
t1.Join();     // Wait for thread t1 to complete execution

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

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...