请检查我的多线程代理检查器代码。它总是检查相同的代理。我想我需要使用锁吗?但是当我使用锁时,它只使用一个线程。但通常它是多线程的。这是怎么回事?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Threading;
namespace ProxyChecker
{
public partial class Main : Form
{
public Main()
{
InitializeComponent();
}
private void clearButton_Click(object sender, EventArgs e)
{
proxyList.Items.Clear();
}
private void clearButton2_Click(object sender, EventArgs e)
{
checkedList.Items.Clear();
}
Thread[] checkerThread;
int checking;
int beenChecked;
private bool isRunning;
private delegate void filterProxyHandler(int Index, bool Valid);
static readonly object _locker = new object();
private void startButton_Click(object sender, EventArgs e)
{
checkerThread = new Thread[Convert.ToInt32(threadBox.Text)];
checking = proxyList.Items.Count;
isRunning = true;
beenChecked = 1;
for (int i = 0; i <= Convert.ToInt32(threadBox.Text) - 1; i++)
{
checkerThread[i] = new Thread(new ParameterizedThreadStart(checkProxys));
checkerThread[i].Start(i);
}
}
public void checkProxys(object Index)
{
int index = (int)Index;
while (isRunning)
{
if (beenChecked >= checking)
isRunning = false;
if (index >= proxyList.Items.Count)
{
checkerThread[index].Abort();
}
string occoultProxy = proxyList.Items[index].ToString();
object[] validArgs = { index, true };
object[] invalidArgs = { index, false };
try
{
WebProxy proxy;
proxy = new WebProxy(occoultProxy.Split(':')[0], Convert.ToInt32(occoultProxy.Split(':')[1]));
WebRequest web = WebRequest.Create(serverBox.Text.ToString());
web.Proxy = proxy;
web.Timeout = Convert.ToInt32(timeoutbox.Text);
web.GetResponse();
if (proxyList.InvokeRequired)
{
proxyList.Invoke(new filterProxyHandler(filterProxy), validArgs);
}
else
{
filterProxy(index, true);
}
beenChecked++;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
if (proxyList.InvokeRequired)
proxyList.Invoke(new filterProxyHandler(filterProxy), invalidArgs);
else
filterProxy(index, false);
beenChecked++;
}
}
}
void filterProxy(int index, bool Valid)
{
try
{
if (Valid)
{
checkedList.Items.Add(proxyList.Items[index]);
//proxyList.Items.RemoveAt(index);
}
else
{
//proxyList.Items.RemoveAt(index);
}
}
catch
{
}
}
private void stopButton_Click(object sender, EventArgs e)
{
isRunning = false;
for (int i = 0; i <= Convert.ToInt32(threadBox.Text) - 1; i++) {
checkerThread[i].Abort();
}
}
private void Main_Load(object sender, EventArgs e)
{
CheckForIllegalCrossThreadCalls = false;
}
}
}
答案 0 :(得分:5)
一个问题:beenChecked++;
不是线程安全的
请改用Interlocked.Increment(ref beenChecked);
。
另外,
checkedList.Items.Add(proxyList.Items[index]);
不安全。你需要lock() { ... }
或使用并发集合。
其余的似乎相当安全,但不能担保。
但是当我使用锁时,它只使用一个线程。
您没有发布该代码,因此无法发表评论。有很多方法可以解决锁定问题。
答案 1 :(得分:0)
每个线程都在检查自己的代理,因此看起来你不需要任何锁定。
但是beenChecked
确实需要某种形式的锁定。例如Interlocked.Increment
。您也可以在那里使用lock
,但为此目的,这可能会非常繁重。 Interlocked
用于执行此类操作。
另一个说明;您有一点在正在运行的线程上调用Abort
。这不是必要的;您需要做的就是从停止线程的方法return
。