@@ -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