Reworked proxy checker threading, fixed the bug where it would stop halfway.

This commit is contained in:
ruri
2019-05-25 15:53:48 +02:00
parent 5b3d126736
commit ad44543e41
2 changed files with 134 additions and 80 deletions
+131 -80
View File
@@ -23,46 +23,21 @@ namespace OpenBullet
/// </summary> /// </summary>
public partial class ProxyManager : Page public partial class ProxyManager : Page
{ {
AbortableBackgroundWorker bw = new AbortableBackgroundWorker();
public ProxyManagerViewModel vm = new ProxyManagerViewModel(); public ProxyManagerViewModel vm = new ProxyManagerViewModel();
private GridViewColumnHeader listViewSortCol = null; private GridViewColumnHeader listViewSortCol = null;
private SortAdorner listViewSortAdorner = null; private SortAdorner listViewSortAdorner = null;
bool stop = false; private WorkerStatus Status = WorkerStatus.Idle;
private CancellationTokenSource cts = new CancellationTokenSource();
public ProxyManager() public ProxyManager()
{ {
InitializeComponent(); InitializeComponent();
DataContext = vm; DataContext = vm;
bw.DoWork += new DoWorkEventHandler(Check);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CheckComplete);
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.Status = WorkerStatus.Idle;
vm.RefreshList(); vm.RefreshList();
vm.UpdateProperties(); vm.UpdateProperties();
} }
private void Check(object sender, DoWorkEventArgs e)
{
stop = false;
ThreadPool.SetMinThreads(vm.BotsNumber*2, vm.BotsNumber*2);
Globals.LogInfo(Components.ProxyManager, "Set the minimum threads");
//ThreadPool.SetMaxThreads(1000, 1000);
Parallel.ForEach(vm.OnlyUntested ? vm.ProxyList.Where(p => p.Working == ProxyWorking.UNTESTED) : vm.ProxyList,
new ParallelOptions { MaxDegreeOfParallelism = vm.BotsNumber }, (proxy, state) =>
{
if (stop) { Globals.LogWarning(Components.ProxyManager, "Abort signal received, breaking the state"); state.Break(); }
CheckCountry(proxy);
CheckProxy(proxy);
App.Current.Dispatcher.Invoke(new Action(() => vm.UpdateProperties()));
});
}
private void CheckCountry(CProxy proxy) private void CheckCountry(CProxy proxy)
{ {
try try
@@ -90,7 +65,10 @@ namespace OpenBullet
} }
} }
catch (Exception ex) { Globals.LogError(Components.ProxyManager, "Failted to check country for proxy '" + proxy.Proxy + $"' - {ex.Message}"); } catch (Exception ex)
{
Globals.LogError(Components.ProxyManager, "Failted to check country for proxy '" + proxy.Proxy + $"' - {ex.Message}");
}
} }
private void CheckProxy(CProxy proxy) private void CheckProxy(CProxy proxy)
@@ -101,11 +79,15 @@ namespace OpenBullet
using (var request = new HttpRequest()) using (var request = new HttpRequest())
{ {
request.Proxy = proxy.GetClient(); request.Proxy = proxy.GetClient();
request.ConnectTimeout = (int)vm.Timeout; request.Proxy.ConnectTimeout = (int)vm.Timeout * 1000;
request.Proxy.ReadWriteTimeout = (int)vm.Timeout * 1000;
request.ConnectTimeout = (int)vm.Timeout * 1000;
request.KeepAliveTimeout = (int)vm.Timeout * 1000;
request.ReadWriteTimeout = (int)vm.Timeout * 1000;
var response = request.Get(vm.TestURL); var response = request.Get(vm.TestURL);
var source = response.ToString(); var source = response.ToString();
App.Current.Dispatcher.Invoke(new Action(() => proxy.Ping = (DateTime.Now - before).Milliseconds)); App.Current.Dispatcher.Invoke(new Action(() => proxy.Ping = (int)(DateTime.Now - before).TotalMilliseconds));
App.Current.Dispatcher.Invoke(new Action(() => proxy.Working = source.Contains(vm.SuccessKey) ? ProxyWorking.YES : ProxyWorking.NO)); App.Current.Dispatcher.Invoke(new Action(() => proxy.Working = source.Contains(vm.SuccessKey) ? ProxyWorking.YES : ProxyWorking.NO));
@@ -124,52 +106,112 @@ namespace OpenBullet
} }
} }
#region Start Button
private void CheckComplete(object sender, RunWorkerCompletedEventArgs e)
{
Globals.LogInfo(Components.ProxyManager, "Check completed, re-enabling the UI");
checkButton.Content = "CHECK";
botsSlider.IsEnabled = true;
bw.Status = WorkerStatus.Idle;
}
private void botsSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
vm.BotsNumber = (int)e.NewValue;
}
private void checkButton_Click(object sender, RoutedEventArgs e) private void checkButton_Click(object sender, RoutedEventArgs e)
{ {
switch (bw.Status) switch (Status)
{ {
case WorkerStatus.Idle: case WorkerStatus.Idle:
stop = false;
Globals.LogInfo(Components.ProxyManager, "Disabling the UI and starting the checker"); Globals.LogInfo(Components.ProxyManager, "Disabling the UI and starting the checker");
checkButton.Content = "ABORT"; checkButton.Content = "ABORT";
botsSlider.IsEnabled = false; botsSlider.IsEnabled = false;
bw.RunWorkerAsync(); Status = WorkerStatus.Running;
bw.Status = WorkerStatus.Running; #pragma warning disable CS4014 // Non è possibile attendere la chiamata, pertanto l'esecuzione del metodo corrente continuerà prima del completamento della chiamata
CheckProxiesAsync(vm.ProxyList, vm.BotsNumber, 200);
#pragma warning restore CS4014 // Non è possibile attendere la chiamata, pertanto l'esecuzione del metodo corrente continuerà prima del completamento della chiamata
break; break;
case WorkerStatus.Running: case WorkerStatus.Running:
stop = true;
Globals.LogWarning(Components.ProxyManager, "Abort signal sent"); Globals.LogWarning(Components.ProxyManager, "Abort signal sent");
checkButton.Content = "HARD ABORT"; checkButton.Content = "HARD ABORT";
bw.Status = WorkerStatus.Stopping; Status = WorkerStatus.Stopping;
cts.Cancel();
break; break;
case WorkerStatus.Stopping: case WorkerStatus.Stopping:
Globals.LogWarning(Components.ProxyManager, "Hard abort signal sent"); Globals.LogWarning(Components.ProxyManager, "Hard abort signal sent");
bw.CancelAsync(); checkButton.Content = "CHECK";
botsSlider.IsEnabled = true;
Status = WorkerStatus.Idle;
break; break;
} }
} }
#endregion
private void importButton_Click(object sender, RoutedEventArgs e) #region Check
public async Task CheckProxiesAsync(IEnumerable<CProxy> proxies, int threads, int step)
{ {
(new MainDialog(new DialogAddProxies(this), "Import Proxies")).ShowDialog(); var proxiesToCheck = vm.OnlyUntested ? proxies.ToList() : proxies.Where(p => p.Working == ProxyWorking.UNTESTED).ToList();
// The semaphore will only allow {limit} elements at most running at the same time.
using (var semaphore = new SemaphoreSlim(threads, threads))
{
cts = new CancellationTokenSource();
for (int i = 0; i < proxiesToCheck.Count; i += step)
{
var tasks = proxiesToCheck
.Skip(i)
.Take(Math.Min(proxiesToCheck.Count - i, step))
.Select(p => CheckProxyAsync(p, semaphore, cts.Token))
.ToArray();
try
{
await Task.WhenAny(Task.WhenAll(tasks), AsTask(cts.Token));
cts.Token.ThrowIfCancellationRequested();
}
catch
{
break;
}
}
App.Current.Dispatcher.Invoke(() =>
{
Globals.LogInfo(Components.ProxyManager, "Check completed, re-enabling the UI");
checkButton.Content = "CHECK";
botsSlider.IsEnabled = true;
Status = WorkerStatus.Idle;
});
}
} }
public static Task AsTask(CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<object>();
cancellationToken.Register(() => tcs.TrySetCanceled(), useSynchronizationContext: false);
return tcs.Task;
}
public async Task CheckProxyAsync(CProxy proxy, SemaphoreSlim semaphore, CancellationToken token)
{
await semaphore.WaitAsync(token).ConfigureAwait(false);
try
{
token.ThrowIfCancellationRequested();
if (Status != WorkerStatus.Running) throw new OperationCanceledException();
// We do it like this, otherwise if we make the requests async the ping measurement won't work
await Task.Run(new Action(() =>
{
CheckCountry(proxy);
CheckProxy(proxy);
App.Current.Dispatcher.Invoke(new Action(() => vm.UpdateProperties()));
}));
}
catch (OperationCanceledException)
{
Globals.LogInfo(Components.ProxyManager, $"{proxy} - THROWING");
throw;
}
finally
{
semaphore.Release();
}
}
#endregion
public void AddProxies(string fileName, ProxyType type, List<string> lines) public void AddProxies(string fileName, ProxyType type, List<string> lines)
{ {
List<string> fromFile = new List<string>(); List<string> fromFile = new List<string>();
@@ -229,7 +271,12 @@ namespace OpenBullet
vm.UpdateProperties(); vm.UpdateProperties();
} }
#region GUI Controls
private void botsSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
vm.BotsNumber = (int)e.NewValue;
}
private void exportButton_Click(object sender, RoutedEventArgs e) private void exportButton_Click(object sender, RoutedEventArgs e)
{ {
SaveFileDialog sfd = new SaveFileDialog(); SaveFileDialog sfd = new SaveFileDialog();
@@ -257,7 +304,6 @@ namespace OpenBullet
} }
} }
private void deleteButton_Click(object sender, RoutedEventArgs e) private void deleteButton_Click(object sender, RoutedEventArgs e)
{ {
Globals.LogInfo(Components.ProxyManager, $"Deleting {proxiesListView.SelectedItems.Count} proxies"); Globals.LogInfo(Components.ProxyManager, $"Deleting {proxiesListView.SelectedItems.Count} proxies");
@@ -268,7 +314,6 @@ namespace OpenBullet
Globals.LogInfo(Components.ProxyManager, "Proxies deleted successfully"); Globals.LogInfo(Components.ProxyManager, "Proxies deleted successfully");
} }
private void DeleteProxies(List<CProxy> proxies) private void DeleteProxies(List<CProxy> proxies)
{ {
Globals.LogInfo(Components.ProxyManager, "Deleting selected proxies"); Globals.LogInfo(Components.ProxyManager, "Deleting selected proxies");
@@ -286,7 +331,6 @@ namespace OpenBullet
vm.UpdateProperties(); vm.UpdateProperties();
} }
private void deleteAllButton_Click(object sender, RoutedEventArgs e) private void deleteAllButton_Click(object sender, RoutedEventArgs e)
{ {
Globals.LogWarning(Components.ProxyManager, "Purging all proxies"); Globals.LogWarning(Components.ProxyManager, "Purging all proxies");
@@ -300,7 +344,6 @@ namespace OpenBullet
vm.UpdateProperties(); vm.UpdateProperties();
} }
private void deleteNotWorkingButton_Click(object sender, RoutedEventArgs e) private void deleteNotWorkingButton_Click(object sender, RoutedEventArgs e)
{ {
Globals.LogInfo(Components.ProxyManager, "Deleting all non working proxies"); Globals.LogInfo(Components.ProxyManager, "Deleting all non working proxies");
@@ -318,24 +361,9 @@ namespace OpenBullet
vm.UpdateProperties(); vm.UpdateProperties();
} }
private void listViewColumnHeader_Click(object sender, RoutedEventArgs e) private void importButton_Click(object sender, RoutedEventArgs e)
{ {
GridViewColumnHeader column = (sender as GridViewColumnHeader); (new MainDialog(new DialogAddProxies(this), "Import Proxies")).ShowDialog();
string sortBy = column.Tag.ToString();
if (listViewSortCol != null)
{
AdornerLayer.GetAdornerLayer(listViewSortCol).Remove(listViewSortAdorner);
proxiesListView.Items.SortDescriptions.Clear();
}
ListSortDirection newDir = ListSortDirection.Ascending;
if (listViewSortCol == column && listViewSortAdorner.Direction == newDir)
newDir = ListSortDirection.Descending;
listViewSortCol = column;
listViewSortAdorner = new SortAdorner(listViewSortCol, newDir);
AdornerLayer.GetAdornerLayer(listViewSortCol).Add(listViewSortAdorner);
proxiesListView.Items.SortDescriptions.Add(new SortDescription(sortBy, newDir));
} }
private void copySelectedProxies_Click(object sender, RoutedEventArgs e) private void copySelectedProxies_Click(object sender, RoutedEventArgs e)
@@ -352,11 +380,6 @@ namespace OpenBullet
catch (Exception ex) { Globals.LogError(Components.ProxyManager, $"Failed to copy proxies - {ex.Message}"); } catch (Exception ex) { Globals.LogError(Components.ProxyManager, $"Failed to copy proxies - {ex.Message}"); }
} }
private void ListViewItem_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
}
private void deleteDuplicatesButton_Click(object sender, RoutedEventArgs e) private void deleteDuplicatesButton_Click(object sender, RoutedEventArgs e)
{ {
var dupeList = vm.ProxyList var dupeList = vm.ProxyList
@@ -396,5 +419,33 @@ namespace OpenBullet
vm.UpdateProperties(); vm.UpdateProperties();
} }
#endregion
#region ListView
private void listViewColumnHeader_Click(object sender, RoutedEventArgs e)
{
GridViewColumnHeader column = (sender as GridViewColumnHeader);
string sortBy = column.Tag.ToString();
if (listViewSortCol != null)
{
AdornerLayer.GetAdornerLayer(listViewSortCol).Remove(listViewSortAdorner);
proxiesListView.Items.SortDescriptions.Clear();
}
ListSortDirection newDir = ListSortDirection.Ascending;
if (listViewSortCol == column && listViewSortAdorner.Direction == newDir)
newDir = ListSortDirection.Descending;
listViewSortCol = column;
listViewSortAdorner = new SortAdorner(listViewSortCol, newDir);
AdornerLayer.GetAdornerLayer(listViewSortCol).Add(listViewSortAdorner);
proxiesListView.Items.SortDescriptions.Add(new SortDescription(sortBy, newDir));
}
private void ListViewItem_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
}
#endregion
} }
} }
+3
View File
@@ -88,8 +88,11 @@ namespace RuriLib
catch (OpenQA.Selenium.WebDriverTimeoutException) catch (OpenQA.Selenium.WebDriverTimeoutException)
{ {
data.Log(new LogEntry("Timeout on Page Load", Colors.Tomato)); data.Log(new LogEntry("Timeout on Page Load", Colors.Tomato));
if (BanOnTimeout) if (BanOnTimeout)
{
data.Status = BotStatus.BAN; data.Status = BotStatus.BAN;
}
} }
data.Driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(data.GlobalSettings.Selenium.PageLoadTimeout); data.Driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(data.GlobalSettings.Selenium.PageLoadTimeout);