如何在多线程应用程序中使用锁?

时间:2012-10-09 20:09:59

标签: c# multithreading sockets locking

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

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

2 个答案:

答案 0 :(得分:5)

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

另外,

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

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

其余的似乎相当安全,但不能担保。

  

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

您没有发布该代码,因此无法发表评论。有很多方法可以解决锁定问题。

答案 1 :(得分:0)

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

但是beenChecked确实需要某种形式的锁定。例如Interlocked.Increment。您也可以在那里使用lock,但为此目的,这可能会非常繁重。 Interlocked用于执行此类操作。

另一个说明;您有一点在正在运行的线程上调用Abort。这不是必要的;您需要做的就是从停止线程的方法return