镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

RestClient.Execute() is extremely slow compared to RestClient.ExecuteAsync().Result #2375

Open

Description

@tyuah8

Describe the bug
RestClient.Execute() is extremely slow compared to RestClient.ExecuteAsync().Result, when called in a parallel setting, even though both are synchronous.

To Reproduce

private class CustomInterceptor : Interceptor
{
    public override ValueTask BeforeDeserialization ( RestResponse response, CancellationToken cancellationToken )
    {
        response.ContentType = ContentTypes.application_json;
        return ValueTask.CompletedTask;
    }
}

static void Test02 ()
{
    //
    const int total = 100;
    int width = ( int ) Math.Ceiling( Math.Log10( total ) );
    ( int, TimeSpan )[] elapsed = new ( int, TimeSpan )[total];
    //

    RestResponse    Execute    ( RestClient c, string resource, Method method, Action<RestRequest> callback )
    {
        //
        RestRequest     i;
        RestResponse    o;
        //

        if ( c == null )
            throw new ArgumentNullException( nameof( c ) );

        i = new RestRequest( resource, method );
        callback?.Invoke( i );
        i.Interceptors = [];
        i.Interceptors.Add( new CustomInterceptor() );
        o = c.Execute( i );
        return o;
    }

    void Test ( int i )
    {
        //
        Stopwatch watch;
        //

        static void Add ( RestRequest t )
        {
            t.AddHeader( HTTPHeaders.Content_Type, ContentTypes.application_json );
        }

        watch = Stopwatch.StartNew();
        using ( var c = new RestClient( some server ) )
            Execute( c, "", Method.Post, Add );

        watch.Stop();
        elapsed[i] = ( i, watch.Elapsed );
    }

    Parallel.For( 0, total, Test );

    ////

    Array.Sort( elapsed, ( x, y ) => y.Item2.CompareTo( x.Item2 ) );
    for ( int i = 0; i < total; i++ )
        Console.WriteLine( $@"{elapsed[i].Item1.ToString().PadLeft( width )} => {elapsed[i].Item2:mm\:ss\.fff}" );
}

If you use the above code, which uses c.Execute( i ), to communicate to a server, there will be very long delays (up to roughly 10 s). If you replace c.Execute( i ) with c.ExecuteAsync( i ).Result, the time is reduced to just roughly 1 s.

Expected behavior
Since both RestClient.Execute() and RestClient.ExecuteAsync().Result are synchronous, both should have the exact same performance.

Desktop

  • OS: Windows 11
  • .NET 8.0
  • Version 114.0.0

Activity

  1. tyuah8 commented on Apr 27, 2026

    @tyuah8
    Author

    Is this related to #2372?

  2. deAtog commented on Apr 30, 2026

    @deAtog

    Calling RestClient.Execute() is not quite the same as calling RestClient.ExecuteAsync().Result. RestClient.Execute() currently uses a CustomSynchronizationContext in an attempt to do async in a synchronous manner. This implementation currently does not work as expected. In WinForms applications, calling RestClient.Execute() from the UI thread currently causes a deadlock. RestClient.ExecuteAsync().Result can also cause a deadlock in these cases.

    I'd be interested to see what your results are if you compare it against Task.Run(() => RestClient.ExecuteAsync()).GetAwaiter().GetResult() as this is my proposed change to avoid deadlocks. This avoids the deadlock at the cost of using one thread pool thread per synchronous call.

  3. tyuah8 commented on Apr 30, 2026

    @tyuah8
    Author

    I assume the deadlocking is only when used in WinForms and there is no such issue in ASP.NET Core?

  4. deAtog commented on Apr 30, 2026

    @deAtog

    Accessing Task.Result can result in a deadlock for a WinForms or WPF application, or in a Classic ASP.NET web application. Excessively calling Task.Result in an ASP.NET Core application can lead to a deadlock due to thread starvation of the thread pool. Using Task.Run to run an async method can lead to the same result. Awaiting the async version of the method is undoubtedly the best option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions