【发布时间】:2013-01-04 19:19:29
【问题描述】:
我有一个带有 URL 列表的 ListBox。
我有 2 个线程获取这些 URL 并将它们处理成一个函数。
我的线程 1 使用 ListBox 的 items[0],我的线程 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();
});
}
【问题讨论】:
-
只有主线程(GUI Thread)才能访问像ListBox这样的GUI组件。如果你使用后台线程来访问一个 GUI 组件,它最终会失败。
-
你应该使用
ConcurrentQueue<T>。 -
if (myQueue.Count > 0)是非常错误的。摆脱它。 -
您的标签文字也有误。您应该将原始项目数存储在单独的字段中。
标签: c# multithreading thread-safety simultaneous-calls