-1

マルチスレッドプロキシチェッカーコードを確認してください。常に同じプロキシをチェックしています。これにはロックを使用する必要があると思いますか?しかし、私がロックを使用するとき、それはたった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

1 つの問題:beenChecked++;はスレッドセーフではありません。代わりに
使用してください。Interlocked.Increment(ref beenChecked);

また、

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

安全ではありません。lock() { ... }これを回避するか、並行コレクションを使用する必要があります。

残りはかなり安全だと思われますが、それを保証することはできません.

しかし、ロックを使用すると、1 つのスレッドだけで動作します。

そのコードを投稿しなかったため、コメントできません。ロックを間違える方法はたくさんあります。

于 2012-10-09T20:14:52.367 に答える
0

各スレッドは独自のプロキシをチェックしているため、ロックはまったく必要ないようです。

ただしbeenChecked、何らかの形式のロックが必要です。Interlocked.Increment、 例えば。そこでも使用できますlockが、その目的には不必要に重いです。Interlockedそのような操作を行うために作られています。

別のメモ; ある時点Abortで、実行中のスレッド自体を呼び出しています。これは必要ありません。returnメソッドからスレッドを停止するだけです。

于 2012-10-09T20:15:07.177 に答える