18

次のコードを使用しています。

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

ユーザーが有効なユーザー名とパスワードを入力すると、すべて問題ありません。ユーザーが間違ったユーザー名とパスワードを入力すると、最初の試行では「Not Enter」メッセージが正しく表示されますが、2 回目の試行では次のメッセージが表示されます。

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

このエラーが発生しないようにコードを修正するにはどうすればよいですか?

4

3 に答える 3

16

Srv_LoginChannelFactory.Close()それが処分されている場所です。closeと呼ぶと、管理されていないリソースをすべて放棄することになります。状態を検査するか、再度開く以外のことを行おうとすると、「破棄されたオブジェクトにアクセスできません」という例外が発生します。

これは、使い捨てのオブジェクトを閉じて、後でそれを使って何かをしようとするときはいつでも当てはまります。たとえば、閉じられたファイルへの書き込み、または閉じられたデータベース接続でのsqlステートメントの実行。

これに対処するには、3つのオプションがあります。

  1. Srv_LoginChannelFactoryをフィールドにしないでください。代わりに、ボタンクリックに対してローカルにします。これが使用している唯一の場所である場合、これはおそらく、管理されていないリソースを使用している時間を短縮するため、これを行うのが理にかなっています。

  2. IDisposableを実装します(Disposableのフィールドがある場合は常にこれを行うことになっています)。Login.Disposeを除いて、Srv_LoginChannelFactoryを閉じないでください。

  3. ボタンをクリックしてSrv_LoginChannelFactoryの状態を確認してから、それを使用してチャネルを作成してください。ボタンのクリックが発生しない場合に備えて、IDisposableを実装する必要があります。

EnsureOpenedは状態の確認に使用できるように見えますが、開く前にのみ機能します。閉じられるとスローされます。

Close()がDisposeと同じであることについて。

クラスライブラリを開発するための設計ガイドラインの管理されていないリソースをクリーンアップするためのファイナライズと破棄の実装の「破棄メソッド名のカスタマイズ」のセクションから

場合によっては、Disposeよりもドメイン固有の名前の方が適切な場合があります。たとえば、ファイルのカプセル化では、メソッド名Closeを使用できます。この場合、Disposeをプライベートに実装し、Disposeを呼び出すパブリックCloseメソッドを作成します。次のコード例は、このパターンを示しています。Closeは、ドメインに適したメソッド名に置き換えることができます。この例では、システム名前空間が必要です。

ここでの考え方は、Openメソッドに同等性を与えることです。個人的には混乱を招くと思いますが、これ以上のことは考えられません(CloseAndDispose?)

于 2011-01-01T08:33:26.010 に答える
2

ここでの問題 (コンラッドが見逃したと思う) は、おそらくチャネル (LoginService) だけを閉じたいときに、すべてのチャネルを閉じる (破棄する) ChannelFactory (Srv_LoginChannelFactory) を Kerezo が閉じていることです。

だから変更:

    Srv_LoginChannelFactory.Close();

に:

    try
    {
        LoginService.Close();
    }
    catch
    {
        LoginService.Abort();
    }
于 2013-11-14T03:41:01.280 に答える
-2

それを使用する前に Serialized と deserialize を使用して、ファイルをオリジナルにする For Serializing オブジェクト

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);
于 2018-08-19T22:55:19.060 に答える