-1

请检查我的多线程代理检查器代码。它总是检查相同的代理。我想我需要为此使用锁?但是当我使用锁时,它只使用一个线程。但通常它是多线程的。这是什么问题?

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;
        }
    }
}
4

2 回答 2

5

一个问题:beenChecked++;不是线程安全的。
改为使用Interlocked.Increment(ref beenChecked);

还,

 checkedList.Items.Add(proxyList.Items[index]);

不安全。你需要一个lock() { ... }围绕这个或使用并发集合。

其余的似乎相当安全,但不能保证这一点。

但是当我使用锁时,它只使用一个线程。

您没有发布该代码,因此无法发表评论。有很多方法可以使锁定错误。

于 2012-10-09T20:14:52.367 回答
0

每个线程都在检查自己的代理,因此看起来您不需要任何锁定。

不过,您beenChecked确实需要某种形式的锁定。Interlocked.Increment, 例如。你也可以lock在那里使用,但这对于那个目的来说是不必要的沉重。Interlocked是为进行这种操作而设计的。

另一个注意事项;您在某一时刻调用Abort正在运行的线程本身。这不是必需的;您需要做的就是return从方法中停止线程。

于 2012-10-09T20:15:07.177 回答