-
Notifications
You must be signed in to change notification settings - Fork 151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cancellation token #164
Cancellation token #164
Conversation
Workarounds like But you can publish it as your own NuGet package (such as a package named |
According to the documentation the outstanding async requests are cancelled if the socket is closed.
Whenever the socket is created by the library it is used inside an I've also verified this behaviour with the following unit test: public class SocketTestFixture
{
[Fact]
public async Task TestReceiveIsAborted()
{
var receiveWasAborted = false;
var receiver = new IPEndPoint(IPAddress.Loopback, 11337);
using (new UdpClient(receiver))//listen to prevent ICMP unreachable
using (var socket = receiver.GetSocket())
{
using (var cts = new CancellationTokenSource())
{
try
{
await socket.SendToAsync(new ArraySegment<byte>(Array.Empty<byte>()), SocketFlags.None, receiver);
var receive = ReceiveAsync(socket, cts.Token, ReceiveMessageFromAsync);
cts.Cancel();
await receive;
}
catch(TaskCanceledException)
{
//that's expected, we just cancelled the token
}
}
}
await Task.Delay(100);//yield is not enough to execute the catch
Assert.True(receiveWasAborted);
async Task ReceiveMessageFromAsync(Socket socket)
{
try
{
var buffer = new ArraySegment<byte>(new byte[10]);
EndPoint remote = new IPEndPoint(IPAddress.Any, 0);
await socket.ReceiveMessageFromAsync(buffer, SocketFlags.None, remote);
}
catch
{
receiveWasAborted = true;
throw;
}
}
}
private async Task ReceiveAsync(Socket socket, CancellationToken cancellationToken, Func<Socket, Task> receiverWrapper)
{
var cancellation = Task.Delay(Timeout.Infinite, cancellationToken);
var receive = receiverWrapper(socket);
var result = await Task.WhenAny(receive, cancellation).ConfigureAwait(false);
await result;
await receive.ConfigureAwait(false);
}
} If the socket is passed in via the caller, we cannot guarantee that the socket is diposed properly, so I'm thinking about removing the cancellationToken from all public methods, which have a socket parameter. Then it would be the responsibility of the caller to abort the request by closing the socket (instead of passing a cancellationToken). |
We actually allow users of the library to reuse their As far as I can see, the workaround in this pull request will not work well for those overloading methods and might require extra steps. I rather have the true cancellation support for all cases (sadly .NET 6 only) than accepting a workaround that only supports a few cases (but like I explained above you can publish a separate NuGet package for whoever wants that). |
No plan to accept this pull request as discussed above. Close it now to avoid confusion. Active work is in https://github.com/lextudio/sharpsnmplib/tree/net6 to bring native cancellation support to this library. |
I've added an optional CancellationToken parameter to all async methods. Cancellation is handled in
SocketExtension.SendToAsync
andSocketExtension.ReceiveMessageFromAsync
.I've also added some missing
ConfigureAwait(false)
and removed some unneededasync/await
fixes #140