什么可能导致“无法访问已处置的对象"?WCF 中的错误? [英] What could be causing a "Cannot access a disposed object" error in WCF?

查看:32
本文介绍了什么可能导致“无法访问已处置的对象"?WCF 中的错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下代码:

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

登录是我的构造函数:

public Login()
        {
            InitializeComponent(); 
            ws = new WSHttpBinding();
            Srv_Login_EndPoint = new EndpointAddress("http://localhost:2687/Srv_Login.svc");
            Srv_LoginChannelFactory = new ChannelFactory<Srv_Login.Srv_ILogin>(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();
    }
}

当用户输入有效的用户名和密码时,一切正常.当用户输入错误的用户名和密码时,第一次尝试正确显示未输入"消息,但在第二次尝试时,用户看到此消息:

When the user enters a valid username and password, everything is fine. When the user enters a wrong username and password, the first try correctly displays a "Not Enter" message, but on the second try, the user sees this message:

{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()

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

How can I fix my code to prevent this error from occurring?

推荐答案

Srv_LoginChannelFactory.Close() 是处理它的地方.当您调用 close 时,您将放弃您拥有的任何非托管资源.尝试执行其他操作然后检查其状态或重新打开它会导致无法访问已处理的对象"异常.

Srv_LoginChannelFactory.Close() is where it's being disposed. When you call close you are giving up whatever unmanaged resource you had. Attempting to do something other then inspecting its state or re-opening it results in the "Cannot access a disposed object" exception.

每当您关闭一次性物品并在之后尝试对其进行处理时,都是如此.例如写入关闭的文件,或在关闭的数据库连接上执行 sql 语句.

This is true whenever you close a disposable object and try and do something with it afterwards. For example writing to a file that's closed, or executing a sql statement on a closed database connection.

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

To address this you have three options.

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

  1. Don't make the Srv_LoginChannelFactory a field. Instead make it local to the button click. If this is the only place you are using it, this probably makes sense to do because it shortens the amount of time you are using an unmanaged resource.

实现 IDisposable(只要有 Disposable 字段,就应该这样做)不要关闭 Srv_LoginChannelFactory,除了 Login.Dispose.

Implement IDisposable (you are supposed do this whenever you have field that is Disposable) don't close Srv_LoginChannelFactory except in Login.Dispose.

在尝试使用它创建频道之前,更改按钮单击以检查 Srv_LoginChannelFactory 的状态.你仍然需要实现 IDisposable 以防按钮点击没有发生.

Change the button click to check the State of Srv_LoginChannelFactory before you try and create a channel with it. You still need to implement IDisposable in case the button click doesn't happen.

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

Note: EnsureOpened looks like it could be used to check the state, but it only works before its opened. Once its been closed it will throw.

关于 Close() 与 Dispose 相同.

Regarding Close() being the same as Dispose.

来自 实施 Finalize 和 Dispose 中的自定义处置方法名称"部分开发类库的设计指南中的清理非托管资源

有时特定于域的名称是比 Dispose 更合适.为了例如,文件封装可能想用方法名关闭.在在这种情况下,私下实施 Dispose并创建一个公共 Close 方法调用处置.以下代码示例说明了这种模式.你可以用方法名替换 Close适合您的域.这示例需要 System 命名空间.

Occasionally a domain-specific name is more appropriate than Dispose. For example, a file encapsulation might want to use the method name Close. In this case, implement Dispose privately and create a public Close method that calls Dispose. The following code example illustrates this pattern. You can replace Close with a method name appropriate to your domain. This example requires the System namespace.

这里的想法是为 Open 方法提供奇偶校验.我个人认为这会引起很多混乱,但我想不出更好的方法(CloseAndDispose?)

The idea here is to give parity to the Open method. Personally I think it causes a lot of confusion, but I can't think of anything better (CloseAndDispose?)

这篇关于什么可能导致“无法访问已处置的对象"?WCF 中的错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆