0
votes

I need to send parallel several Post requests. For this I'm going to use the following code:

        try
        {
            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"key={customer.FCMServerKey}");

                var obj = new
                {
                    to = customer.FcmRegistrationId,
                    notification = new
                    {
                        title = push.PushTitle,
                        body = push.PushBody,
                    }
                };

                string json = JsonConvert.SerializeObject(obj);
                var data = new StringContent(json, Encoding.UTF8, "application/json");

                responseTasks.Add( client.PostAsync("https://fcm.googleapis.com/fcm/send", data));
                pushes.Add(push);
            }
        }
        catch (HttpRequestException ex)
        {

            Console.WriteLine("\nException with pushing!");
            Console.WriteLine("Message :{0} ", ex.Message);
        }

    }

    var responses = await Task.WhenAll(responseTasks);

    var count = 0;
    foreach (var response in responses)
    {
        var responseBody = await response.Content.ReadAsStringAsync();

        pushes[count].FCMResponse = responseBody;
        pushes[count].Sent = response.IsSuccessStatusCode;

        Console.WriteLine("FCM response:");
        Console.WriteLine(pushes[count].FCMResponse);

        count++;
    }

    await _pushRepository.SaveAsync(pushes);
}

As you can see, I put my task objects into the responseTasks. Then I'm going to send all requests with the help of this line:

var responses = await Task.WhenAll(responseTasks);

I as result I have this exception:

Unhandled Exception: System.Threading.Tasks.TaskCanceledException: The operation was canceled. ---> System.ObjectDisposedException: Cannot access a disposed object. Object name: 'System.Net.Sockets.NetworkStream'. at System.Net.Sockets.NetworkStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 size, CancellationToken cancellationToken) at System.IO.Stream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count) at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult) at System.Net.Security.SslStream.BeginAuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions, CancellationToken cancellationToken, AsyncCallback asyncCallback, Object asyncState) at System.Net.Security.SslStream.<>c.b__47_0(SslClientAuthenticationOptions arg1, CancellationToken arg2, AsyncCallback callback, Object state) at System.Threading.Tasks.TaskFactory1.FromAsyncImpl[TArg1,TArg2](Func5 beginMethod, Func2 endFunction, Action1 endAction, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions) at System.Threading.Tasks.TaskFactory.FromAsync[TArg1,TArg2](Func5 beginMethod, Action1 endMethod, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions) at System.Threading.Tasks.TaskFactory.FromAsync[TArg1,TArg2](Func5 beginMethod, Action1 endMethod, TArg1 arg1, TArg2 arg2, Object state) at System.Net.Security.SslStream.AuthenticateAsClientAsync(SslClientAuthenticationOptions sslClientAuthenticationOptions, CancellationToken cancellationToken) at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken) --- End of inner exception stack trace --- at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)

What is wrong?

1

1 Answers

3
votes

please check how using works: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement

In your code client will be disposed as soon as using block ends but you still have pending tasks on responseTasks list that will try to access it. You need to get results while in client using block.