Csharp/C#教程:什么可能导致WCF中的“无法访问已处置的对象”错误?分享


什么可能导致WCF中的“无法访问已处置的对象”错误?

我使用以下代码:

private WSHttpBinding ws; private EndpointAddress Srv_Login_EndPoint; private ChannelFactory Srv_LoginChannelFactory; private Srv_Login.Srv_ILogin LoginService; 

Login是我的构造函数:

 public Login() { InitializeComponent(); ws = new WSHttpBinding(); Srv_Login_EndPoint = new EndpointAddress("https://localhost:2687/Srv_Login.svc"); Srv_LoginChannelFactory = new ChannelFactory(ws, Srv_Login_EndPoint); } 

我正在以这种方式使用服务:

 private void btnEnter_Click(object sender, EventArgs e) { try { LoginService = Srv_LoginChannelFactory.CreateChannel(); Srv_Login.LoginResult res = new Srv_Login.LoginResult(); res = LoginService.IsAuthenticated(txtUserName.Text.Trim(), txtPassword.Text.Trim()); if (res.Status == true) { int Id = int.Parse(res.Result.ToString()); } else { lblMessage.Text = "Not Enter"; } } catch (Exception ex) { MessageBox.Show(ex.Message); } finally { Srv_LoginChannelFactory.Close(); } } 

当用户输入有效的用户名和密码时,一切都很好。 当用户输入错误的用户名和密码时,第一次尝试正确显示“未输入”消息,但在第二次尝试时,用户会看到以下消息:

 {System.ObjectDisposedException: Cannot access a disposed object. Object name: 'System.ServiceModel.ChannelFactory`1[Test_Poosesh.Srv_Login.Srv_ILogin]'. at System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposed() at System.ServiceModel.ChannelFactory.EnsureOpened() at System.ServiceModel.ChannelFactory`1.CreateChannel(EndpointAddress address, Uri via) at System.ServiceModel.ChannelFactory`1.CreateChannel() 

如何修复代码以防止发生此错误?

Srv_LoginChannelFactory.Close()是它被处置的地方。 当你打电话给你时,你放弃了你拥有的任何非托管资源。 尝试执行其他操作然后检查其状态或重新打开它会导致“无法访问已处置对象”exception。

无论何时关闭一次性物体并尝试随后对其进行操作,都是如此。 例如,写入已关闭的文件,或在已关闭的数据库连接上执行sql语句。

要解决这个问题,您有三种选择。

  1. 不要将Srv_LoginChannelFactory设为字段。 而是将其设置为按钮单击的本地。 如果这是您使用它的唯一位置,这可能是有意义的,因为它缩短了您使用非托管资源的时间。

  2. 实现IDisposable(只要你有一个Disposable字段就可以这样做)除了Login.Dispose之外,不要关闭Srv_LoginChannelFactory。

  3. 在尝试使用它创建通道之前,请更改按钮单击以检查Srv_LoginChannelFactory的状态。 如果没有按钮单击,您仍然需要实现IDisposable。

注意 : EnsureOpened看起来可用于检查状态,但它仅在打开之前有效。 一旦关闭它就会抛出。

关于Close()与Dispose相同。

从开发类库的设计指南中的实现完成和处理以清理非托管资源的 “自定义Dispose方法名称”一节

有时,特定于域的名称比Dispose更合适。 例如,文件封装可能希望使用方法名称Close。 在这种情况下,请私下实现Dispose并创建一个调用Dispose的公共Close方法。 以下代码示例说明了此模式。 您可以使用适合您的域的方法名称替换Close。 此示例需要System命名空间。

这里的想法是给Open方法赋予奇偶校验。 我个人认为这会导致很多混乱,但我想不出更好的事情(CloseAndDispose?)

这里的问题(我认为Conrad错过了)是Kerezo正在关闭ChannelFactory(Srv_LoginChannelFactory),它关闭(处置)所有通道,当他可能只想关闭Channel(LoginService)时。

所以改变:

  Srv_LoginChannelFactory.Close(); 

至:

  try { LoginService.Close(); } catch { LoginService.Abort(); } 

使用序列化和反序列化之前,使文件原始为序列化对象

 var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; var SerializedFile = JsonConvert.SerializeObject(file, settings); 

和反序列化对象

上述就是C#学习教程:什么可能导致WCF中的“无法访问已处置的对象”错误?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

 var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; var getUserObj = JsonConvert.DeserializeObject("SERIALIZED_OBJ", settings); 

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/984309.html

(0)
上一篇 2021年12月20日
下一篇 2021年12月20日

精彩推荐