Что может быть причиной ошибки «Не удается получить доступ к удаленному объекту» в WCF? - PullRequest
15 голосов
/ 01 января 2011

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

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

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

Ответы [ 3 ]

16 голосов
/ 01 января 2011

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

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

Для решения этой проблемы у вас есть три варианта.

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

  2. Реализация IDisposable (вы должны делать это всякий раз, когда у вас есть поле Disposable), не закрывайте Srv_LoginChannelFactory, за исключением Login.Dispose.

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

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

Относительно того, что Close () совпадает с Dispose.

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

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

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

2 голосов
/ 14 ноября 2013

Проблема здесь (которую, я думаю, пропустил Конрад) заключается в том, что Керезо закрывает ChannelFactory (Srv_LoginChannelFactory), который закрывает (удаляет) все его каналы, когда он, вероятно, хочет закрыть только канал (LoginService).* Так измените:

    Srv_LoginChannelFactory.Close();

на:

    try
    {
        LoginService.Close();
    }
    catch
    {
        LoginService.Abort();
    }
0 голосов
/ 20 августа 2018

используйте Serialized и десериализацию перед использованием, что делает файл оригинальным для объекта сериализации

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...