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

发布于 2024-10-09 21:49:12 字数 1826 浏览 0 评论 0原文

我使用以下代码:

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();
    }
}

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

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

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

I am using the following code:

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

The Login is my constructor:

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);
        }

And I'm using service this way:

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

别挽留 2024-10-16 21:49:12

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

每当您关闭一次性物品并随后尝试用它做某事时,都是如此。例如,写入已关闭的文件,或在已关闭的数据库连接上执行 sql 语句。

为了解决这个问题,您有三个选择。

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

  2. 实现 IDisposable(只要您有 Disposable 字段,您就应该执行此操作)除了 Login.Dispose 之外,不要关闭 Srv_LoginChannelFactory。

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

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

关于 Close() 与 Dispose 相同。

来自实现 Finalize 和 Dispose 以清理非托管中的“自定义 Dispose 方法名称”部分开发类库设计指南中的资源

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

这里的想法是给予 Open 方法同等的机会。就我个人而言,我认为这会引起很多混乱,但我想不出更好的东西(CloseAndDispose?)

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.

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. 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.

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

  3. 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.

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.

Regarding Close() being the same as Dispose.

From the section 'Customizing a Dispose Method Name' in Implementing Finalize and Dispose to Clean Up Unmanaged Resources in the Design Guidelines for Developing Class Libraries

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.

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?)

戈亓 2024-10-16 21:49:12

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

因此将:更改

    Srv_LoginChannelFactory.Close();

为:

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

The problem here (which I think Conrad missed) is that Kerezo is closing the ChannelFactory (Srv_LoginChannelFactory) which closes (disposes) all its channels, when he probably wants to close just the Channel (LoginService).

So change:

    Srv_LoginChannelFactory.Close();

to:

    try
    {
        LoginService.Close();
    }
    catch
    {
        LoginService.Abort();
    }
赏烟花じ飞满天 2024-10-16 21:49:12

使用序列化并在使用之前反序列化
这使文件成为原始文件
用于序列化对象

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

和用于反序列化对象

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

use Serialized and deserialize before using it
that makes file original
For Serializing object

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

and For deserializing Object

var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };        
var getUserObj = JsonConvert.DeserializeObject<OBJECT_TYPE>("SERIALIZED_OBJ", settings);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文