一部のライブラリは非同期メソッドのみを提供しますが、ASP.net は確かに同期です。つまり、ページが表示されるまでコールバック関数が実行されないという問題が発生しました。そして、私が必要とするプロセスは、ページをレンダリングする前にコールバック関数で検証を実行することです。 Mutex と AutoResetEvent は、セマフォを通じてスレッドの実行ステップを調整するメソッドを提供します。
XmppClientConnection は、agsxmppJabber ライブラリ内のクラスです。Open を呼び出すと、成功したかどうかに関係なく、すぐにクライアントに戻り、ページが表示されます。同時に、別のスレッドがログインと新しいアカウントの操作を実行します。成功するとコールバック イベントがトリガーされるため、コールバックはページがレンダリングされた後にのみ実行されますが、これは必要なロジックに準拠しません。 Open を呼び出すスレッドを Jabber スレッド、ログインを実行するスレッドを Jabber スレッドの補助スレッドと呼びます。
私の最初のアイデアは、Monitor を使用することでした。コードは次のとおりです。
プライベート オブジェクト objlock=new object();
public void RegisterJab(string ユーザー名、string パスワード、string サーバー)
{
_connection.Server = サーバー;
_connection.ユーザー名 = ユーザー名;
_connection.Password = パスワード;
_connection.ポート = 80;
_connection.UseSSL = false;
_connection.AutoResolveConnectServer = true;
_connection.ConnectServer = null;
_connection.SocketConnectionType = agsXMPP.net.SocketConnectionType.Direct;
_connection.UseStartTLS = true;
_connection.RegisterAccount = true;
Monitor.Enter(objlock);
_connection.Open();
Monitor.Wait(objlock);
_connection.Close()
;
private void XmppCon_OnRegistered(オブジェクト送信者)
{
IsSuccessfull = true;
Monitor.Exit(objlock);
}
Jabber 補助スレッドがロックの所有者ではないため、Monitor.Exit(): SynchronizationLockException を実行すると例外がスローされます。Monitor はクリティカル セクションのようなものであり、この状況の処理には適していないことがわかります。
その後、Mutex に移行しました。Mutex: は、共有リソースへの排他的アクセスを 1 つのスレッドにのみ許可する同期プリミティブです。 1 つのスレッドがミューテックスを取得すると、最初のスレッドがミューテックスを解放するまで、ミューテックスを取得する 2 番目のスレッドは一時停止されます。
Mutex はこの機能を実現するのに非常に適していますが、もっと簡単な方法はありますか?それが AutoResetEvent で、スレッドがシグナリングによって相互に通信できるようにします。通常、この通信には、スレッドが排他的アクセスを必要とするリソースが含まれます。最も重要なことは、スレッド間の通信方法を提供し、スレッドの呼び出しステップをより柔軟に制御できるようにすることです。それがセマフォです。
コード:
名前空間 LoginBase
{
パブリッククラス登録
{
XmppClientConnection_接続;
静的 AutoResetEvent myResetEvent;
パブリックブール値が使用されます。
publicRegister()
{
_connection = 新しい XmppClientConnection();
_connection.SocketConnectionType = agsXMPP.net.SocketConnectionType.Direct;
_connection.OnLogin += 新しい ObjectHandler(XmppCon_OnLogin);
_connection.OnRegisterError += 新しい OnXmppErrorHandler(XmppCon_OnRegErr);
_connection.OnRegistered += 新しい ObjectHandler(XmppCon_OnRegistered)
;
public bool IsSuccessfull = false;
public void RegisterJab(string ユーザー名、string パスワード、string サーバー)
{
_connection.Server = サーバー;
_connection.ユーザー名 = ユーザー名;
_connection.Password = パスワード;
_connection.ポート = 80;
_connection.UseSSL = false;
_connection.AutoResolveConnectServer = true;
_connection.ConnectServer = null;
_connection.SocketConnectionType = agsXMPP.net.SocketConnectionType.Direct;
_connection.UseStartTLS = true;
_connection.RegisterAccount = true;
myResetEvent = 新しい AutoResetEvent(false);
_connection.Open();
myResetEvent.WaitOne(20 * 1000, true);
_connection.Close()
;
private void XmppCon_OnRegistered(オブジェクト送信者)
{
IsSuccessfull = true;
myResetEvent.Set();
private
void XmppCon_OnLogin(オブジェクト送信者)
{
IsSuccessfull = true;
myResetEvent.Set();
}
private void XmppCon_OnRegErr(オブジェクト送信者、要素 e)
{
// errCode が 409 の場合、ユーザーはすでに存在します
IsSuccessfull = false;
要素 xn = e.SelectSingleElement("error");
if (xn.Attribute("code") == "409")
Isused = true;
myResetEvent.Set()
;
}
}
まず非終了状態に設定し、次に Jabber スレッドに入り、Asp スレッドをブロックして待機します。タイムアウトは 20 秒です。コールバック イベントがトリガーされると、ステータスは終了に設定され、ASP スレッドは実行を継続します。
同期は正常に完了するため、Jabber 補助スレッドの実行が終了するまで Asp スレッドは続行されません。
http://www.cnblogs.com/bluewater/archive/2006/08/14/476720.html