Advertisement
stigzler

Untitled

Sep 15th, 2023
744
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.78 KB | None | 0 0
  1. using stigzler.Screenscraper.Data.Models;
  2. using stigzler.Screenscraper.Enums;
  3. using stigzler.Screenscraper.Helpers;
  4. using stigzler.Screenscraper.Services;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Diagnostics;
  8. using System.Linq;
  9. using System.Net;
  10. using System.Net.Http;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13.  
  14. namespace stigzler.Screenscraper
  15. {
  16.     public class GetData
  17.     {
  18.         #region Properties
  19.  
  20.         // Public Members
  21.         public Credentials Credentials { get; set; }
  22.         public ApiServerParameters ApiParameters { get; set; }
  23.         public HttpClient HttpClient { get; set; }
  24.         public MetadataOutput MetadataOutputFormat
  25.         {
  26.             get { return metadataOutputFormat; }
  27.             set
  28.             {
  29.                 metadataOutputFormat = value;
  30.                 urlBuilder.MetadataOutputType = metadataOutputFormat;
  31.             }
  32.         }
  33.         public int UserThreads
  34.         {
  35.             get { return userThreads; }
  36.             set
  37.             {
  38.                 if (value > Data.Constants.MaxApiThreads)
  39.                 { throw new ArgumentException("UserThreads cannot exceed the maximum for the Screenscraper API server: " + Data.Constants.MaxApiThreads); }
  40.                 else
  41.                 {
  42.                     userThreads = value;
  43.                     SetNumberApiThreads();
  44.                 }
  45.             }
  46.         }
  47.  
  48.         // Any Property private members
  49.         private int userThreads = 1;
  50.         private MetadataOutput metadataOutputFormat = MetadataOutput.xml;
  51.         #endregion
  52.  
  53.         // Class level private vars
  54.         private ApiUrlBuilder urlBuilder;
  55.         private GetDataService getDataService;
  56.  
  57.         public GetData(Credentials credentials, ApiServerParameters apiServerParameters, HttpClient httpClient, int userThreads)
  58.         {
  59.             // Set Public Properties
  60.             Credentials = credentials;
  61.             ApiParameters = apiServerParameters;
  62.             HttpClient = httpClient;
  63.             this.userThreads = userThreads;
  64.  
  65.             // Setup getDataService
  66.             getDataService = new GetDataService(apiServerParameters, UserThreads, HttpClient);
  67.             urlBuilder = new ApiUrlBuilder(Credentials, ApiParameters);
  68.  
  69.         }
  70.  
  71.         private void SetNumberApiThreads()
  72.         {
  73.             ServicePointManager.FindServicePoint(new Uri(ApiParameters.HostAddress)).ConnectionLimit = userThreads;
  74.         }
  75.  
  76.         public async Task<ApiGetOutcome> GetApiServerInfo()
  77.         {
  78.             List<string> urlList = new List<string> { urlBuilder.Build(ApiQueryType.ServerInfo) };
  79.             var result = await Task.Run(() => getDataService.GetUrlListData(urlList));
  80.             return result.First(); // First, because this operation only has one entry
  81.         }
  82.  
  83.         public async Task<ApiGetOutcome> GetUserInfo()
  84.         {
  85.             List<string> urlList = new List<string> { urlBuilder.Build(ApiQueryType.UserInfo) };
  86.             var result = await Task.Run(() => getDataService.GetUrlListData(urlList));
  87.             return result.First(); // First, because this operation only has one entry
  88.         }
  89.  
  90.         public async Task<List<ApiGetOutcome>> GetGameInfo(int systemID, List<string> romNames)
  91.         {
  92.             List<QueryParameter> parameters = new List<QueryParameter>();
  93.  
  94.             List<string> urlList = new List<string>();
  95.  
  96.             foreach (string romname in romNames)
  97.             {
  98.                 parameters.Clear();
  99.                 parameters.Add(new QueryParameter() { Parameter = ApiQueryParameter.RomFilename, Value = romname });
  100.                 parameters.Add(new QueryParameter() { Parameter = ApiQueryParameter.SystemID, Value = systemID.ToString() });
  101.  
  102.                 urlList.Add(urlBuilder.Build(ApiQueryType.GameInfo, parameters));
  103.             }
  104.  
  105.             List<ApiGetOutcome> apiGetOutcomes = new List<ApiGetOutcome>();
  106.  
  107.             ServicePointManager.DefaultConnectionLimit = userThreads;
  108.             ServicePointManager.FindServicePoint(new Uri(ApiParameters.HostAddress)).ConnectionLimit = userThreads;
  109.  
  110.             Stopwatch SW = Stopwatch.StartNew();
  111.  
  112.             ThreadPool.SetMinThreads(100, 100);
  113.  
  114.             // APPROACH 1: Parallel.ForEach
  115.             //Parallel.ForEach(urlList, new ParallelOptions() { MaxDegreeOfParallelism = userThreads }, url =>
  116.             //{
  117.             //    var getResult = HttpClient.GetStringAsync(url);
  118.             //    string json = getResult.Result;
  119.             //    apiGetOutcomes.Add(new ApiGetOutcome() { Data = json, Url = url });
  120.             //    Debug.WriteLine("Rate: " + apiGetOutcomes.Count / SW.Elapsed.TotalSeconds);
  121.             //    Debug.WriteLine(apiGetOutcomes.Count);
  122.             //});
  123.             // OUTCOME 1: steady stream of 1/s
  124.  
  125.  
  126.             // APPROACH 2: Task/Semaphore mix
  127.             //var tasks = new List<Task>();
  128.             //foreach (string url in urlList)
  129.             //{
  130.             //    tasks.Add(PerformApiGet(url, HttpClient));
  131.             //}
  132.             //await Task.WhenAll(tasks);
  133.             // OUTCOME 2: steady stream of 1/s
  134.  
  135.  
  136.  
  137.             // APPROACH 3: Parallel.ForEach using WebClient
  138.             //Parallel.ForEach(urlList, new ParallelOptions() { MaxDegreeOfParallelism = userThreads }, url =>
  139.             //{
  140.             //    using (WebClient wc = new WebClient())
  141.             //    {
  142.             //        var result = wc.DownloadString(new Uri(url));
  143.             //        apiGetOutcomes.Add(new ApiGetOutcome() { Data = result, Url = url });
  144.             //        Debug.WriteLine("Rate: " + apiGetOutcomes.Count / SW.Elapsed.TotalSeconds);
  145.             //        Debug.WriteLine(apiGetOutcomes.Count);
  146.             //    }
  147.             //});
  148.             // OUTCOME 3: steady stream of 5/s
  149.  
  150.  
  151.  
  152.             // APPROACH 4: Charlieface's approach
  153.             var DlTasks = new List<Task>();
  154.             foreach (string url in urlList)
  155.             {
  156.                 if (DlTasks.Count >= UserThreads)
  157.                 {
  158.                     var finished = await Task.WhenAny(DlTasks);
  159.                     DlTasks.Remove(finished);
  160.                 }
  161.                 DlTasks.Add(PerformApiGet(url, HttpClient));
  162.             }
  163.             await Task.WhenAll(DlTasks);
  164.  
  165.             return apiGetOutcomes;
  166.         }
  167.  
  168.         private static readonly SemaphoreSlim semaphore = new SemaphoreSlim(7);
  169.         private async Task PerformApiGet(string url, HttpClient httpClient)
  170.         {
  171.             await semaphore.WaitAsync();
  172.             try
  173.             {
  174.                 var response = await httpClient.GetStringAsync(url);
  175.                 Debug.WriteLine("Downloaded: " + response.Length);
  176.             }
  177.             finally
  178.             {
  179.                 semaphore.Release();
  180.             }
  181.         }
  182.     }
  183. }
  184.  
Tags: httpclient
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement