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