我使用以下代码:
private WSHttpBinding ws;
private EndpointAddress Srv_Login_EndPoint;
private ChannelFactory<Srv_Login.Srv_ILogin> Srv_LoginChannelFactory;
private Srv_Login.Srv_ILogin LoginService;
Login是我的构造函数:
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()
如何修复代码以防止发生此错误?
Srv_LoginChannelFactory.Close()
是它被处置的地方。当你打电话给你时,你放弃了你拥有的任何非托管资源。尝试执行其他操作然后检查其状态或重新打开它会导致“无法访问已处置对象”异常。
每当你关闭一次性物体并尝试用它做一些事情时,这都是正确的。例如,写入已关闭的文件,或在已关闭的数据库连接上执行sql语句。
要解决这个问题,您有三种选择。
注意:EnsureOpened看起来可以用来检查状态,但它只能在打开之前工作。一旦关闭它就会抛出。
关于Close()与Dispose相同。
从开发类库的设计指南中的Implementing Finalize and Dispose to Clean Up Unmanaged Resources中的“自定义处理方法名称”一节
有时,特定于域的名称比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);
和反序列化对象
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
var getUserObj = JsonConvert.DeserializeObject<OBJECT_TYPE>("SERIALIZED_OBJ", settings);