mono / mono

Mono open source ECMA CLI, C# and .NET implementation.
https://www.mono-project.com
Other
11.13k stars 3.83k forks source link

HttpClient with HttpClientHandler cancellation not working #19357

Open heebaek opened 4 years ago

heebaek commented 4 years ago

I use Xamarin forms. After update of visual studio for mac, this bug appear again(i think i saw this bug in old version)

task cancellation exception will be throwing after so many seconds.

may be this bug is related... https://xamarin.github.io/bugzilla-archives/13/13200/bug.html

below are copy of my vs for mac about page.

=== Visual Studio Community 2019 for Mac ===

Version 8.5 (build 3183) Installation UUID: 883cf3b7-25cd-491f-a1c1-02f553d644ea GTK+ 2.24.23 (Raleigh theme) Xamarin.Mac 6.14.1.39 (d16-5 / 30e8706b4)

Package version: 608000123

=== Mono Framework MDK ===

Runtime: Mono 6.8.0.123 (2019-10/1d0d939dc30) (64-bit) Package version: 608000123

=== Roslyn (Language Service) ===

3.5.0-beta4-20125-04+1baa0b3063238ed752ad1f0368b1df6b6901373e

=== NuGet ===

버전: 5.4.0.6315

=== .NET Core SDK ===

SDK: /usr/local/share/dotnet/sdk/3.1.201/Sdks SDK 버전: 3.1.201 MSBuild SDK: /Library/Frameworks/Mono.framework/Versions/6.8.0/lib/mono/msbuild/Current/bin/Sdks

=== .NET Core 런타임 ===

런타임: /usr/local/share/dotnet/dotnet 런타임 버전: 3.1.3 3.1.2 2.1.16

=== Xamarin.Profiler ===

버전:1.6.13.11 위치:/Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler

=== Updater ===

버전: 11

=== Apple Developer Tools ===

Xcode 11.4 (16134) Build 11E146

=== Xamarin.Mac ===

Version: 6.14.1.39 (Visual Studio Community) Hash: 30e8706b4 Branch: d16-5 Build date: 2020-02-20 16:41:47-0500

=== Xamarin Designer ===

Version: 16.5.0.471 Hash: 35aa4889d Branch: remotes/origin/d16-5 Build date: 2020-02-25 00:52:08 UTC

=== Xamarin.Android ===

버전:10.2.0.100 (Visual Studio Community) Commit: xamarin-android/d16-5/988c811 Android SDK: /Users/bobaman/Library/Developer/Xamarin/android-sdk-macosx Supported Android versions: None installed

SDK Tools Version: 26.1.1 SDK Platform Tools Version: 29.0.5 SDK Build Tools Version: 29.0.2

Build Information: Mono: c0c5c78 Java.Interop: xamarin/java.interop/d16-5@fc18c54 ProGuard: xamarin/proguard/master@905836d SQLite: xamarin/sqlite/3.28.0@46204c4 Xamarin.Android Tools: xamarin/xamarin-android-tools/d16-5@9f4ed4b

=== Microsoft Mobile OpenJDK ===

Java SDK: /Users/bobaman/Library/Developer/Xamarin/jdk/microsoft_dist_openjdk_1.8.0.25 1.8.0-25 Android Designer EPL code available here: https://github.com/xamarin/AndroidDesigner.EPL

=== Android SDK Manager ===

Version: 16.5.0.39 Hash: 6fb4c79 Branch: remotes/origin/d16-5 Build date: 2020-02-20 23:25:56 UTC

=== Android Device Manager ===

Version: 16.5.0.71 Hash: 49194e8 Branch: remotes/origin/d16-5 Build date: 2020-02-20 23:26:18 UTC

=== Xamarin.iOS ===

Version: 13.14.1.39 (Visual Studio Community) Hash: 30e8706b4 Branch: d16-5 Build date: 2020-02-20 16:41:48-0500

=== Xamarin Inspector ===

Version: 1.4.3 Hash: db27525 Branch: 1.4-release Build date: Mon, 09 Jul 2018 21:20:18 GMT Client compatibility: 1

=== Build Information ===

Release ID: 805003183 Git revision: 60e06e010baa677204535600661dda3fb4677c2f Build date: 2020-03-20 06:18:03-04 Build branch: release-8.5 Xamarin extensions: 60e06e010baa677204535600661dda3fb4677c2f

=== Operating System ===

Mac OS X 10.15.3 Darwin 19.3.0 Darwin Kernel Version 19.3.0 Thu Jan 9 20:58:23 PST 2020 root:xnu-6153.81.5~1/RELEASE_X86_64 x86_64

DevEddy commented 3 years ago

Wow, how can this bug be ignored? Or ist there a workaround?

Same issue here, the timeout seems not to be respected. The weird thing is that my request timeouts after 134 seconds on Android and after 75 seconds on iOS.

UWP is working as expected with the same code.

https://github.com/xamarin/Xamarin.Forms/issues/10214

@heebaek any news on your side?

Thanks, Eddy

heebaek commented 3 years ago

@DevEddy no good news :(

I am using very ugly manual waiting code...

this code just for cancellation. but if you want, you can add timeout logic there.

    public static async Task<string> GetStringAsync(this HttpClient client, string url, CancellationToken token)
    {
        var task = client.GetAsync(url, HttpCompletionOption.ResponseContentRead, token);
        if (!await task.WaitUntil(token))
            return null;

        using (var resp = await task)
        {
            if (!resp.IsSuccessStatusCode)
                return null;
            return await resp.Content.ReadAsStringAsync();
        }
    }

    public static async Task<bool> WaitUntil(this Task thisTask, CancellationToken token)
    {
        while (!thisTask.IsCompleted && !token.IsCancellationRequested)
        {
            await Task.Delay(100);
        }
        return thisTask.Status == TaskStatus.RanToCompletion;
    }
redradist commented 3 years ago

I've have the same issue with Xamarin.Forms testing on Android ... It seems like cancellation sometimes works sometimes not ...

Is there a fix for it ?

flimtix commented 3 years ago

Thanks @heebaek for your code. I still have some concerns about the implementation. What happens to the task when the token is executed? If you return null the task still runs in the background as far as I know. Now what happens if an error message is issued?

heebaek commented 3 years ago

I am not sure about it. it is not easy to find exact document. but I think no-one wait async task, exception will be swallowed. exception will be saved in Task.Exception property and Task.IsFaulted will be set. but will not crash. just nobody care.

flimtix commented 3 years ago

I tried around a bit and noticed that the timout is strangely observed when sending data. That means it is simply aborted. Please fix the HttpClient...

riskeez commented 2 years ago

Hi there, I've experienced the same issue.

Doesn't work on:

My setup:

Code example:

using System.Net.Http;

....
var httpHandler = new HttpClientHandler() { AutomaticDecompression = System.Net.DecompressionMethods.GZip };
var httpClient = new HttpClient(httpHandler) { Timeout = DefaultTimeout };

....
await httpClient.SendAsync(request, cancellationToken: token);

Just nothing happens when you request token cancellation. No errors, no additional info in output

As a workaround now using approach like this: Task.WhenAny(requestTask, Task.Delay(DefaultTimeout, token));