Skip to content

Commit e345f8c

Browse files
author
Your Name
committed
Fix
1 parent 8e8d140 commit e345f8c

3 files changed

Lines changed: 45 additions & 18 deletions

File tree

README.md

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,31 @@ It runs in the background, periodically refreshes the lists, and re-checks proxi
66

77
## Quick Start
88

9+
Typical usage:
10+
911
```csharp
1012
using InfiniteProxy;
1113

12-
var client = new InfiniteProxyClient(new InfiniteProxyOptions
14+
var client = new InfiniteProxyClient();
15+
16+
// This starts the background scraping + checking and waits until
17+
// at least one working proxy is available.
18+
await client.WaitUntilReadyAsync();
19+
20+
var proxy = client.GetRandom(ProxyType.Http)!;
21+
22+
// Use it with HttpClient
23+
var handler = new HttpClientHandler
1324
{
14-
ProxyTypes = [ProxyType.Http, ProxyType.Socks5],
15-
FetchInterval = TimeSpan.FromMinutes(5),
16-
CheckTimeout = TimeSpan.FromSeconds(10),
17-
ConnectTimeout = TimeSpan.FromSeconds(6)
18-
});
25+
Proxy = new WebProxy(proxy.Host, proxy.Port),
26+
UseProxy = true
27+
};
28+
using var http = new HttpClient(handler);
1929

20-
var first = await client.StartAsync();
21-
Console.WriteLine($"Ready: {first}");
30+
var html = await http.GetStringAsync("https://example.com");
2231
```
2332

24-
After `StartAsync` returns you have at least one working proxy and the scanner continues running.
33+
After `WaitUntilReadyAsync()` returns, the pool has at least one good proxy and the scanner continues running in the background.
2534

2635
## Using a Proxy + Handling Failures
2736

examples/QuickStart/Program.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
client.ProxyRemoved += (_, e) => Console.WriteLine($"[-] {e.Proxy}");
1414

1515
Console.WriteLine("Starting InfiniteProxy background scanner...");
16-
Console.WriteLine("Waiting for the first working proxy...\n");
16+
Console.WriteLine("Waiting until at least one working proxy is available...\n");
1717

18-
var first = await client.StartAsync();
19-
Console.WriteLine($"\nFirst proxy ready: {first}");
18+
await client.WaitUntilReadyAsync();
19+
20+
var proxy = client.GetRandom(ProxyType.Http)!;
21+
Console.WriteLine($"First proxy ready: {proxy}");
2022
Console.WriteLine($"Pool size: {client.WorkingCount}");
2123

2224
var fastest = client.GetFastest();

src/InfiniteProxy/InfiniteProxyClient.cs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,29 @@ public event EventHandler<ProxyRemovedEventArgs>? ProxyRemoved
9292
}
9393

9494
/// <summary>
95-
/// Starts the 24/7 background scanner and completes once at least one working proxy is available.
95+
/// Starts the background scanner and returns the first working proxy once one is available.
96+
/// This is a convenience method on top of <see cref="WaitUntilReadyAsync"/>.
9697
/// </summary>
9798
/// <param name="cancellationToken">Cancel waiting for the first proxy. The scanner keeps running unless <see cref="StopAsync"/> is called.</param>
9899
/// <returns>The first validated proxy endpoint.</returns>
99100
public async Task<ProxyEndpoint> StartAsync(CancellationToken cancellationToken = default)
101+
{
102+
await WaitUntilReadyAsync(cancellationToken).ConfigureAwait(false);
103+
return _pool.GetRandom()!;
104+
}
105+
106+
/// <summary>
107+
/// Ensures the background scraping and checking loop is running,
108+
/// then completes once at least one working proxy is available.
109+
///
110+
/// This is the recommended method when you just want to wait until the client
111+
/// has at least one good proxy before proceeding.
112+
/// </summary>
113+
public async Task WaitUntilReadyAsync(CancellationToken cancellationToken = default)
100114
{
101115
ObjectDisposedException.ThrowIf(_disposed == 1, this);
102116

117+
// Start the constant scraping + validation background loop (only once)
103118
if (Interlocked.CompareExchange(ref _started, 1, 0) == 0)
104119
{
105120
_cts = new CancellationTokenSource();
@@ -108,23 +123,24 @@ public async Task<ProxyEndpoint> StartAsync(CancellationToken cancellationToken
108123

109124
if (_pool.Count > 0)
110125
{
111-
return _pool.GetRandom()!;
126+
return;
112127
}
113128

114-
var waitTcs = new TaskCompletionSource<ProxyEndpoint>(TaskCreationOptions.RunContinuationsAsynchronously);
129+
// Wait until the background scanner adds the first valid proxy
130+
var waitTcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
115131
EventHandler<ProxyAddedEventArgs>? handler = null;
116-
handler = (_, args) => waitTcs.TrySetResult(args.Proxy);
132+
handler = (_, _) => waitTcs.TrySetResult(true);
117133
_pool.ProxyAdded += handler;
118134

119135
try
120136
{
121137
await using var registration = cancellationToken.Register(static state =>
122138
{
123-
var tcs = (TaskCompletionSource<ProxyEndpoint>)state!;
139+
var tcs = (TaskCompletionSource<bool>)state!;
124140
tcs.TrySetCanceled();
125141
}, waitTcs).ConfigureAwait(false);
126142

127-
return await waitTcs.Task.ConfigureAwait(false);
143+
await waitTcs.Task.ConfigureAwait(false);
128144
}
129145
finally
130146
{

0 commit comments

Comments
 (0)