线程没有同时运行?

时间:2017-07-17 20:10:36

标签: c# .net multithreading

首先,我知道标题并非完全“独特”,但它是一个特定的问题,请在将其标记为重复之前阅读。

我创建了一个访问网页并在多个线程上登录帐户的应用程序。现在..我已经测试了几次,但它没有出现奇怪的结果。它从字典中选择一个随机帐户并尝试使用它登录(多个线程)。

这是为每个线程

创建一个类的bot处理程序
class BotHandler
{
    private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();

    private readonly ConcurrentDictionary<string, KeyValuePair<string, int>> _que;
    private readonly ConcurrentDictionary<int, BotInfo> _accounts;
    private readonly Dictionary<int, Bot> _Bots;

    private readonly Random _random = new Random();
    private readonly object locker = new object();

    public ConcurrentDictionary<string, KeyValuePair<string, int>> Que => _que;

    public BotHandler()
    {
        _que = new ConcurrentDictionary<string, KeyValuePair<string, int>>();
        _accounts = new ConcurrentDictionary<int, BotInfo>();
        _Bots = new Dictionary<int, Bot>();

        _que.TryAdd("username", new KeyValuePair<string, int>("add", 12));
    }

    public void LoadBots()
    {
        var config = Program.GetServer().GetConfigHandler();

        using (var dbConnection = Program.GetServer().GetDatabaseManager().GetConnection())
        {
            dbConnection.SetQuery("SELECT * FROM `_bot_accounts` WHERE `enabled` = '1'");
            var table = dbConnection.ExecuteTable();

            foreach (DataRow row in table.Rows)
            {
                _accounts.TryAdd(_accounts.Count + 1, new BotInfo(
                    Convert.ToString(row["username"]), 
                    Convert.ToString(row["password"]),
                    DateTime.ParseExact(Convert.ToString(row["last_used"]), "yyyy-MM-dd HH:mm:ss", CultureInfo.CurrentCulture)));
            }
        }

        Logger.Warn("Loaded " + _accounts.Count + "  bots.");

        for (int i = config.GetValueByKeyInt("_bot.bot_count"); i > 0; i--)
        {
            _Bots.Add(_Bots.Count + 1, new Bot(_Bots.Count + 1));
        }
    }

    public void StartBots()
    {
        foreach (var Bot in _Bots.Values)
        {
            Bot.Start();
        }
    }

    public KeyValuePair<string, KeyValuePair<string, int>> GetCurrentQue()
    {
        return _que.First();
    }

    public KeyValuePair<int, BotInfo> GetAccount()
    {
        var account = new KeyValuePair<int, BotInfo>();

        var randomlyOrdered = _accounts.OrderBy(i => _random.Next());

        lock (locker)
        {
            foreach (KeyValuePair<int, BotInfo> entry in randomlyOrdered)
            {
                if (!entry.Value.Usable())
                    continue;

                account = entry;
            }
        }

        if (!CoreUtilities.IsDefault(account))
        {
            using (var databaseConnection = Program.GetServer().GetDatabaseManager().GetConnection())
            {
                databaseConnection.SetQuery("UPDATE `_bot_accounts` SET `last_used` = '" + 
                    DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "' WHERE `username` = '" + account.Key + "' LIMIT 1");
            }

            account.Value.LastUsed = DateTime.Now;
        }

        return account;
    }
}

博特

using NLog;
using _Bot.Root.Core.Utilities;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;

namespace _Bot.Root.Base.Bots
{
    class Bot
    {
        private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();

        private readonly int _botId;
        private readonly Thread _botThread;

        private bool _working;
        private KeyValuePair<string, KeyValuePair<string, int>> _currentQue;

        private WebBrowser _browser;
        private bool _processing;

        private string _username;

        public Bot(int botId)
        {
            _botId = botId;

            _botThread = new Thread(new ThreadStart(OnCycle));
            _botThread.SetApartmentState(ApartmentState.STA);

            Logger.Trace("BotThread #" + botId + " has been deployed.");
        }

        public void Start()
        {
            _botThread.Start();
        }

        private void OnCycle()
        {
            while (true)
            {
                if (!_working && Program.GetServer().GetBaseHandler().GetBotHandler().Que.Count > 0)
                {
                    StartWorking();
                }
            }
        }

        private void StartWorking()
        {
            if (_working)
            {
                return;
            }

            _working = true;

            if (_browser == null)
            {
                _browser = new WebBrowser()
                {
                    ScriptErrorsSuppressed = true
                };

                _browser.DocumentCompleted += browser_DocumentCompleted;
            }

            _currentQue = Program.GetServer().GetBaseHandler().GetBotHandler().GetCurrentQue();

            if (CoreUtilities.IsDefault(_currentQue))
            {
                Logger.Error("Unable to find a que for thread #" + _botId + "");

                _working = false;
                return;
            }

            _browser.Navigate(StaticSettings.SIGNIN_URL);

            Application.Run();
        }

        private void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            if (_processing)
            {
                return;
            }

            _processing = true;

            try
            {
                var br = sender as WebBrowser;

                if (br.Url == e.Url)
                {
                    var url = e.Url.ToString();

                    if (_browser.DocumentText.Contains("Sign Out"))
                    {
                        Logger.Warn("Logged In: " + _username);

                        /*if (!url.StartsWith(StaticSettings.MAIN_URL + "/" + _currentQue.Key))
                        {
                            _browser.Navigate(StaticSettings.MAIN_URL + "/" + _currentQue.Key);
                        }
                        else
                        {
                            Logger.Info("[Thread #" + _botId + "] Preparing for " + _username + " to " + _currentQue.Value.Key.ToLower() + " " + _currentQue.Key);

                            HtmlElement marryButton = null;

                            foreach (HtmlElement element in br.Document.GetElementsByTagName("button"))
                            {
                                if (element.GetAttribute("data-original-title").ToLower() == _currentQue.Value.Key.ToLower())
                                {
                                    marryButton = element;
                                }
                            }

                            if (marryButton == null)
                            {
                                Logger.Error("Failed to marry " + _currentQue.Key + " on " + _username);
                                return;
                            }

                            marryButton.InvokeMember("click");

                            System.Threading.Thread.Sleep(500);

                            HtmlElement sendButton = null;

                            foreach (HtmlElement element in br.Document.GetElementsByTagName("button"))
                            {
                                if (element.InnerText == "Send" && element.GetAttribute("type") == "submit")
                                {
                                    sendButton = element;
                                }
                            }

                            if (sendButton == null)
                            {
                                Logger.Error("Failed to marry " + _currentQue.Key + " on " + _username);
                                return;
                            }

                            sendButton.InvokeMember("click");
                            sendButton.InvokeMember("click");

                            Logger.Info("[Thread #" + _botId + "] " + _username + " " + _currentQue.Value.Key.ToLower() + " " + _currentQue.Key);

                            _working = false;
                        }*/
                    }
                    else
                    {
                        if (url.StartsWith(StaticSettings.SIGNIN_URL))
                        {
                            foreach (HtmlElement element in br.Document.GetElementsByTagName("div"))
                            {
                                if (element.GetAttribute("className") == "alert alert-danger")
                                {
                                    Logger.Error("Something went wrong...");
                                    Logger.Error(element.InnerText);
                                }
                            }

                                var account = Program.GetServer().GetBaseHandler().GetBotHandler().GetAccount();

                            if (CoreUtilities.IsDefault(account))
                            {
                                Logger.Error("[Thread #" + _botId + "] Failed to find an account");
                                _working = false;
                                return;
                            }

                            _username = account.Value.Username;

                            Logger.Info("Logging In: " + _username);

                            HtmlElement usernameBox = null;
                            HtmlElement passwordBox = null;
                            HtmlElement loginButton = null;

                            foreach (HtmlElement element in br.Document.GetElementsByTagName("input"))
                            {
                                if (element.GetAttribute("name") == "username")
                                {
                                    usernameBox = element;
                                }
                                else if (element.GetAttribute("name") == "password")
                                {
                                    passwordBox = element;
                                }
                                else if (element.GetAttribute("name") == "submit")
                                {
                                    if (element.GetAttribute("value") == "Login with Facebook")
                                    {
                                        continue;
                                    }

                                    loginButton = element;
                                }
                            }

                            if (usernameBox == null || passwordBox == null || loginButton == null)
                            {
                                Logger.Error("Failed to login with " + account.Value.Username);
                                return;
                            }

                            usernameBox.SetAttribute("value", account.Value.Username);
                            passwordBox.SetAttribute("value", account.Value.Password);

                            Logger.Trace("[Thread #" + _botId + "] Logging In: " + _username);

                            System.Threading.Thread.Sleep(100);

                            loginButton.InvokeMember("click");
                        }
                        else
                        {
                            Logger.Trace("Redirecting back to " + StaticSettings.SIGNIN_URL);
                            _browser.Navigate(StaticSettings.SIGNIN_URL);
                        }
                    }
                }
            }
            catch
            {
                Logger.Error("Something went wrong..");
            }
            finally
            {
                _processing = false;
            }
        }
    }
}

好的,因为你可以看到每个“Bot”类都有自己的主题,然后它访问注册URL,一旦它到达注册URL,它将使用从字典中挑选的随机帐户登录。

我已经将日志发送到控制台,以便登录时和登录时。主要问题是每个帐户都会记录其“登录”,然后才会告诉我登录,然后我会开始“登录“日志?当然它会同时发生,而不是等待所有帐户完成访问注册页面并单击登录按钮?

另一个问题是,并非所有帐户都可以进入内部。我会告诉你我的意思。

  21:06:18 - Logging In: newabbie91
  21:06:18 - Logging In: bellav12
  21:06:19 - [Thread #2] Logging In: newabbie91
  21:06:19 - Logging In: ollielittle228
  21:06:19 - [Thread #6] Logging In: bellav12
  21:06:19 - [Thread #4] Logging In: ollielittle228
  21:06:19 - Logging In: alfiedallas704
  21:06:19 - [Thread #7] Logging In: alfiedallas704
  21:06:19 - Logging In: danman192
  21:06:19 - [Thread #5] Logging In: danman192
  21:06:20 - Logging In: alfiekru123
  21:06:20 - [Thread #9] Logging In: alfiekru123
  21:06:21 - Logging In: utuberouter774
  21:06:21 - [Thread #8] Logging In: utuberouter774
  21:06:21 - Logging In: cokepeter915
  21:06:21 - [Thread #1] Logging In: cokepeter915
  21:06:21 - Logging In: aaronalfie520
  21:06:21 - [Thread #10] Logging In: aaronalfie520
  21:06:22 - Logging In: alexmaster9134
  21:06:22 - [Thread #3] Logging In: alexmaster9134
  21:06:29 - Logged In: bellav12
  21:06:29 - Logged In: newabbie91
  21:06:30 - Logged In: ollielittle228
  21:06:30 - Logged In: alfiekru123
  21:06:30 - Logged In: alfiedallas704
  21:06:30 - Logged In: danman192
  21:06:30 - Logged In: utuberouter774
  21:06:30 - Logged In: alexmaster9134
  21:06:31 - Logged In: aaronalfie520
  21:06:33 - Logged In: cokepeter915

你看到会发生什么吗?不是每个帐户都获得“登录”并且通常是9/10,它很少会登录10次,如果我选择较少的线程(例如4或6)但几乎不会有10个线程的10/10 ,大多只是9/10

有人可以解释这种不寻常的行为吗?

0 个答案:

没有答案