Was könnte in WCF einen Fehler mit einem Fehler „auf einen entsorgten Objekt“ verursachen?

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

  •  14-10-2019
  •  | 
  •  

Frage

Ich verwende den folgenden Code:

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

Der Login ist mein Konstruktor:

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

Und ich benutze den Service auf diese Weise:

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

Wenn der Benutzer einen gültigen Benutzernamen und ein gültiges Passwort eingibt, ist alles in Ordnung. Wenn der Benutzer einen falschen Benutzernamen und ein falsches Kennwort eingibt, zeigt der erste Versuch eine Meldung "Nicht eingeben" an, aber beim zweiten Versuch sieht der Benutzer diese Nachricht:

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

Wie kann ich meinen Code beheben, um zu verhindern, dass dieser Fehler auftritt?

War es hilfreich?

Lösung

Srv_LoginChannelFactory.Close() ist dort, wo es entsorgt wird. Wenn Sie schließen, geben Sie die nicht verwaltete Ressource auf, die Sie hatten. Der Versuch, etwas anderes zu tun, dann seinen Zustand zu inspizieren oder wieder zu eröffnen, führt es zu der Ausnahme "nicht auf eine entsorgte Objekt".

Dies gilt, wenn Sie ein Einwegobjekt schließen und versuchen, danach etwas damit zu tun. Zum Beispiel in eine geschlossene Datei schreiben oder eine SQL -Anweisung in einer geschlossenen Datenbankverbindung ausführen.

Um dies zu beheben, haben Sie drei Optionen.

  1. Machen Sie das SRV_LoginChannelfactory nicht zum Feld. Machen Sie es stattdessen lokal zur Schaltfläche Klicken. Wenn dies der einzige Ort ist, an dem Sie es verwenden, ist dies wahrscheinlich sinnvoll, da es die Zeit verkürzt, die Sie mit einer nicht verwalteten Ressource verwenden.

  2. Implementieren Sie idisposable (Sie sollen dies tun, wenn Sie ein Feld haben, das verfügbar ist), schließen Sie srv_loginChannelfactory nur in Login.

  3. Ändern Sie die Schaltfläche Klicken, um den Status von SRV_LoginChannelfactory zu überprüfen, bevor Sie versuchen, einen Kanal damit zu erstellen. Sie müssen weiterhin idisposable implementieren, falls die Schaltfläche nicht stattfindet.

Notiz: Sicherstellen Es sieht so aus, als ob es verwendet werden könnte, um den Zustand zu überprüfen, aber es funktioniert nur, bevor es geöffnet ist. Sobald es geschlossen wurde, wird es werfen.

In Bezug auf Close () das gleiche wie dispose.

Aus dem Abschnitt „Anpassen eines Entsendungsmethodennamens“ in Implementierung der Abschluss und zur Entsorgung, um nicht verwaltete Ressourcen aufzuräumen In den Entwurfsrichtlinien für die Entwicklung von Klassenbibliotheken

Gelegentlich ist ein domänenspezifischer Name angemessener als entsetzt. Beispielsweise möchte eine Dateikapselung möglicherweise den Methodennamenschließung verwenden. In diesem Fall implementieren Sie die Entsendung privat und erstellen Sie eine öffentliche enge Methode, die aufgerufen wird. Das folgende Codebeispiel zeigt dieses Muster. Sie können die Schließung durch einen Methodennamen ersetzen, der Ihrer Domain entspricht. Dieses Beispiel erfordert den Systemnamenspace.

Die Idee hier ist, der offenen Methode Parität zu geben. Persönlich denke ich, dass es viel Verwirrung verursacht, aber ich kann mir nichts Besseres vorstellen (

Andere Tipps

Das Problem hier (von dem ich denke, dass Conrad es verpasst habe) ist, dass Kerezo den Channelforctory (srv_loginChannelfactory) schließt, der alle seine Kanäle schließt (entsorgt), wenn er wahrscheinlich nur den Kanal schließen möchte (LoginService).

Also ändern Sie:

    Srv_LoginChannelFactory.Close();

zu:

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

Verwenden Sie serialisierte und deserialisieren Sie, bevor Sie es verwenden, um die Datei original für das Serialisierungsobjekt zu machen

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

und zum Deserialisierungsobjekt

var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };        
var getUserObj = JsonConvert.DeserializeObject<OBJECT_TYPE>("SERIALIZED_OBJ", settings);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top