Что может вызвать ошибку «не может получить доступ к утилизируемому объекту» в WCF?

StackOverflow https://stackoverflow.com/questions/4573526

  •  14-10-2019
  •  | 
  •  

Вопрос

Я использую следующий код:

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

Как я могу исправить свой код, чтобы предотвратить эту ошибку?

Это было полезно?

Решение

Srv_LoginChannelFactory.Close() где это утилизируется. Когда вы звоните, вы отказываетесь от любого неуправляемого ресурса, который у вас был. Попытка сделать что-то другое, а затем осмотреть его состояние или повторное открытие его исключения «не может получить доступ к утилизируемому объекту».

Это верно, когда вы закрываете одноразовый объект, а затем пытаетесь что -то сделать с ним. Например, написание в файл, который закрыт или выполняет оператор SQL в закрытом подключении базы данных.

Чтобы решить эту проблему, у вас есть три варианта.

  1. Не делайте SRV_Loginchannelfactory поле. Вместо этого сделайте его локальным для кнопки нажмите. Если это единственное место, которое вы используете, это, вероятно, имеет смысл сделать, потому что оно сокращает количество времени, которое вы используете неуправляемый ресурс.

  2. Реализуйте Idisposable (вы должны делать это всякий раз, когда у вас есть поле, которое является одноразовым), не закрывайте srv_loginchannelfactory, кроме как в login.dispose.

  3. Измените кнопку нажмите, чтобы проверить состояние srv_loginchannelfactory, прежде чем попытаться создать канал с ним. Вам все еще нужно реализовать Idisposable, если нажатие кнопки не произойдет.

Примечание: Обеспечить Похоже, его можно использовать для проверки состояния, но он работает только до того, как его открыт. Как только он будет закрыт, он бросится.

Что касается Close () то же самое, что и распоряжение.

Из разделения «Настройка названия метода распоряжения» в Реализация завершения и утилизации для очистки неуправляемых ресурсов В руководящих принципах проектирования для разработки классовых библиотек

Иногда имя, специфичное для домена, более уместно, чем утилизировать. Например, инкапсуляция файла может захотеть использовать имя метода. В этом случае реализуйте распоряжение в частном порядке и создайте общественный метод закрытия, который вызывает распоряжение. Следующий пример кода иллюстрирует этот шаблон. Вы можете заменить закрытие на имя метода, подходящее для вашего домена. Этот пример требует пространства имен системы.

Идея здесь состоит в том, чтобы дать паритет открытому методу. Лично я думаю, что это вызывает большую путаницу, но я не могу думать ни о чем лучше (ClosEanddonspose?)

Другие советы

Проблема здесь (которая, я думаю, пропустил Конрад) заключается в том, что Керезо закрывает Channelfactory (srv_loginchannelfactory), который закрывает (утилизирует) все его каналы, когда он, вероятно, хочет закрыть только канал (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);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top