-
Notifications
You must be signed in to change notification settings - Fork 560
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
Make ServiceChannelProxy implement IAsyncDisposable #5385
Make ServiceChannelProxy implement IAsyncDisposable #5385
Conversation
So that channels created through a `ChannelFactory<T>` without inheriting from `ClientBase<T>` can also benefit from the asynchronous disposal improvements introduced in dotnet#4865. Fixes dotnet#5270
Pros: * Consumer doesn't need to set Client.CacheSetting = CacheSetting.AlwaysOn * Consumer doesn't need to add a constructor that takes a ServiceEndpoint to their partial client class Cons: * Throws on disposal if the channel is in a faulted state (until dotnet/wcf#5385 is merged)
Is there any chance for this to eventually land in a 8.x.x update of the |
Here's why this pull request is important. 😁 https://github.com/0xced/Wcf.HttpClientFactory/blob/6254a6df13fddcd3143c0ece726ccd5778ff15c9/tests/B2BServiceTest.cs#L86-L90 There's a lot going on in my |
This will go into our next 8.x.x release. We don't have a planned release right now, so this will go out in the next release that happens. |
Btw, I think you can work around this by creating another type in DI which wraps the channel and implements IAsyncDisposable. In that, it does a non-throwing Dispose of the client. If I remember right, objects get disposed in a predictable order, I think it's construction order. But if it's the other way around, you can accommodate that too. You would something like this: internal class WcfThrowingDisposeWrapper : IAsyncDisposable
{
public CommunicationObject Disposable { get; set; }
public ValueTask DisposeAsync()
{
if (Disposable == null) return;
try
{
// Only want to close if it is in the Opened state
if (Disposable.State == CommunicationState.Opened)
{
await Task.Factory.FromAsync(Disposable.BeginOpen, Disposable.EndOpen, null);
}
// Anything not closed by this point should be aborted
if (Disposable.State != CommunicationState.Closed)
{
Disposable.Abort();
}
}
catch (CommunicationException)
{
Disposable.Abort();
}
catch (TimeoutException)
{
Disposable.Abort();
}
}
} In the place where you add a factory to create the WCF client, you also create an instance of WcfThrowingDisposeWrapper and set the WCF client on it. Something like this: services.AddScoped<WcfThrowingDisposeWrapper>();
services.AddScoped<IService>(services =>
{
var wrapper = services.GetRequiresService<WcfThrowingDisposeWrapper>();
var channel = services.GetRequiresService<ChannelFactory<IService>>();
wrapper.Disposable = channel;
return channel;
}); When you dispose the scope, it should dispose the |
.NET 9 is going to be released very soon. Are there plans to release either a 8.x.x update with this fix included, or maybe a 9.0.0 version? |
Matt Connew, maintainer of WCF, said that this should be fixed in the next System.ServiceModel.Primitives version. > This will go into our next 8.x.x release. We don't have a planned release right now, so this will go out in the next release that happens. See dotnet/wcf#5385 (comment)
I see that System.ServiceModel.Primitives 8.1.0 has been released and includes this fix. 🥳 |
So that channels created through a
ChannelFactory<T>
without inheriting fromClientBase<T>
can also benefit from the asynchronous disposal improvements introduced in #4865.Fixes #5270