0

I have a line in C# which does not work very reliable and does not time out at all and runs for infinity.

to be more precise i am trying to check the connection to a proxy WebClient.DownloadString

I want it to timeout after 5 seconds without making the full method asynchronous

so the code should be like this:

bool success = false

do_this_for_maximum_5_seconds_or_until_we_reach_the_end
{
WebClient.DownloadString("testurl");
success = true;
}

it will try to download testurl and after it did download it it will set success to true. If DownloadString takes more than 5 seconds, the call is canceled, we do not reach the the line where we set success to true, so it remains false and i know that it field.

The thread will remain frozen while we try to DownloadString, so the action is not taking parallel. The ONLY difference to a normal line would be that we set a timeout after 5 seconds

Please do not suggest alternatives such as using HttpClient, because i need a similar codes also for other places, so i simply want a code which will run in a synchronous application (i have not learned anything about asynchronus programing therefore i would like to avoid it completely)

my approach was like suggested by Andrew Arnott in this thread Asynchronously wait for Task<T> to complete with timeout

however my issue is, I am not exactly sure what type of variable "SomeOperationAsync()" is in his example (i mean it seems like a task, but how can i put actions into the task?), and the bigger issue is that VS wants to switch the complete Method to asynchronos, but i want to run everything synchronous but just with a timeout for a specific line of code.

In case the question has been answered somewhere kindly provide a link

Thank you for any help!!

  • https://stackoverflow.com/questions/1789627/how-to-change-the-timeout-on-a-net-webclient-object – CorrieJanse May 29 '22 at 20:49
  • that solution uses WebRequest and not webclient. besides that i asked not to add a timeout parameter but c# to end this task by itself after x seconds so i can apply it for other issues like this one – Roman Barg May 29 '22 at 20:52
  • Is there any reason you are using `WebClient` and not the newer `HttpClient`? Although it is asynchronous, you can synchronously wait on it along with a timed cancellation token, which will bounce you out after the timeout. – Charlieface May 29 '22 at 20:59
  • i need to check if a proxy server is working. the proxy requires authentication which i do not know how to set up. Besides that i am working on another project with Selenium where I have the same problem when loading a site. the method iteslf does not have a timeout mechanism so i need to set it up externaly. I could maybe find a work around for this case with httpclient/webclient but as i said in the original post, this problem happend a few times for me with other comands – Roman Barg May 29 '22 at 21:46

1 Answers1

-1

You should use Microsoft's Reactive Framework (aka Rx) - NuGet System.Reactive and add using System.Reactive.Linq; - then you can do this:

var downloadString =
    Observable
        .Using(() => new WebClient(), wc => Observable.Start(() => wc.DownloadString("testurl")))
        .Select(x => new { success = true, result = x });

var timeout =
    Observable
        .Timer(TimeSpan.FromSeconds(5.0))
        .Select(x => new { success = false, result = (string)null });
        
var operation = Observable.Amb(downloadString, timeout);

var output = await operation;

if (output.success)
{
    Console.WriteLine(output.result);
}

The first observable downloads your string. The second sets up a timeout. The third, uses the Amb operator to get the result from which ever of the two input observables completes first.

Then we can await the third observable to get its value. And then it's a simple task to check what result you got.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172