C# многопоточность с одновременным доступом к списку> потеря данных (выбор / удаление)

У меня есть ListBox со списком URL-адресов.

У меня есть 2 потока, берущие эти URL-адреса и относящиеся к ним как к функции.

Моя тема 1 занимает items[0] ListBox, и мой поток 2 принимает items[1],

После того, как Нить подняла предмет, она сразу же удаляется, используя Items.RemoveAt(0 or 1)

Моя проблема с использованием этого метода заключается в том, что некоторые URL обрабатываются дважды, а некоторые - нет.

Есть ли способ пометить URL или что-то еще? Я не очень знаком с многопоточностью

PS: в моем примере я сказал, что я использую 2 потока, в действительности я использую 5 потоков.

заранее спасибо

РЕДАКТИРОВАТЬ: использовал concurentqueue система:

    Thread th1;
    Thread th2;
    Thread th3;
    Thread th4;
    Thread th5;
    ConcurrentQueue<string> myQueue= new ConcurrentQueue<string>();
    Int queueCount = 0;

    private void button2_Click(object sender, EventArgs e)
    {
    //initialize objects and query the database
        DBconnect conn;
        conn = new DBconnect();
        string query = "SELECT Url FROM Pages WHERE hash = ''";
        List<string> result = conn.Select(query);
        for (int i = 0; i < result.Count(); i++)
        {
    //For all rows found, add them to the queue
            myQueue.Enqueue(result[i]);
        }
    //start the 5 threads to process the queue              
        th1 = new Thread(ProcessTorrent);
        th2 = new Thread(ProcessTorrent);
        th3 = new Thread(ProcessTorrent);
        th4 = new Thread(ProcessTorrent);
        th5 = new Thread(ProcessTorrent);
        th1.Start();
        th2.Start();
        th3.Start();
        th4.Start();
        th5.Start();

    }


    private void ProcessTorrent()
    {
    //Start an unlimted task with continueWith
        Task tasks = Task.Factory.StartNew(() =>
        {
    //Check if there are still items in the queue
            if (myQueue.Count > 0)
            {
                string queueURL;
                bool haveElement = myQueue.TryDequeue(out queueURL);
        //check if i can get an element from the queue
                if (haveElement)
                {
        //start function to parse the URL and increment the number of items treated from the queue
                    get_torrent_detail(queueElement);
                    Interlocked.Increment(ref queueCount);
                    this.Invoke(new Action(() => label_total.Text = (myQueue.Count() - queueCount).ToString()));

                }
            }
        });
    //continue the task for another queue item
        tasks.ContinueWith(task =>
        {
            ProcessTorrent();
        });
    }

2 ответа

Решение

Похоже, вы используете элемент управления пользовательского интерфейса для координации задач между несколькими потоками.

Это очень плохая идея.

Вместо этого вы должны поставить задачи в ConcurrentQueue<T> или же BlockingCollection<T>и другие потоки должны брать элементы из очереди и обрабатывать их.

Да, это происходит потому, что ой не синхронизирует доступ к списку.

В основном читайте документацию C#, оператор LOCK. Установите замок при доступе к списку. Это предотвращает одновременный доступ к нескольким потокам.

Тогда вы ВСЕГДА получаете верхний элемент (items[0]), немедленно удаляя его.

Я не очень знаком с многопоточностью

Я действительно люблю, когда люди показывают такое отношение. Можете ли вы представить себе повара, который работает в ресторане профессиональным поваром и говорит: "А, я не знаком с духовкой, вы знаете". Или доктор, который говорит: "Хорошо, у меня проблема здесь, я понятия не имею, как сделать укол". Учитывая, что сегодня мы живем в многоцветном мире, это предложение просто кричит в плохом смысле.

Другие вопросы по тегам