Einige Bibliotheken stellen möglicherweise nur asynchrone Methoden bereit, aber ASP.net ist tatsächlich synchron. Diesmal ist ein Problem aufgetreten: Die Rückruffunktion wird erst ausgeführt, wenn die Seite angezeigt wird. Und der Prozess, den ich brauche, ist: Führen Sie eine Überprüfung in der Rückruffunktion durch, bevor die Seite gerendert werden kann. Mutex und AutoResetEvent bieten Methoden zum Koordinieren von Thread-Ausführungsschritten über Semaphoren.
XmppClientConnection ist eine Klasse in der agsxmppJabber-Bibliothek. Der Aufruf von Open führt sofort zum Rendern der Seite durch, unabhängig davon, ob dies erfolgreich ist oder nicht. Gleichzeitig führt ein anderer Thread die Anmelde- und neuen Kontovorgänge aus. Nach Erfolg wird das Rückrufereignis ausgelöst, sodass der Rückruf erst ausgeführt wird, nachdem die Seite gerendert wurde, was nicht der von uns gewünschten Logik entspricht. Wir nennen den Thread, der Open aufruft: Jabber-Thread, und den Thread, der die Anmeldung durchführt: den Hilfsthread des Jabber-Threads.
Meine ursprüngliche Idee war, Monitor zu verwenden, Code:
privates Objekt objlock=new object();
public void RegisterJab(string Benutzername, string Passwort, string server)
{
_connection.Server = server;
_connection.Username = Benutzername;
_connection.Password = Passwort;
_connection.Port = 80;
_connection.UseSSL = false;
_connection.AutoResolveConnectServer = true;
_connection.ConnectServer = null;
_connection.SocketConnectionType = agsXMPP.net.SocketConnectionType.Direct;
_connection.UseStartTLS = true;
_connection.RegisterAccount = true;
Moniter.Enter(objlock);
_connection.Open();
Moniter.Wait(objlock);
_connection.Close()
;
private void XmppCon_OnRegistered(object sender)
{
IsSuccessfull = true;
Moniter.Exit(objlock);
}
Beim Ausführen von Monitor.Exit() wird eine Ausnahme ausgelöst: SynchronizationLockException, da der Jabber-Hilfsthread nicht der Besitzer der Sperre ist. Es wurde festgestellt, dass Monitor wie ein kritischer Abschnitt ist und nicht für die Behandlung dieser Situation geeignet ist.
Später nach Mutex verschoben, ist Mutex: ein Synchronisationsprimitiv, das nur einem Thread exklusiven Zugriff auf eine gemeinsam genutzte Ressource gewährt. Wenn ein Thread einen Mutex erwirbt, wird der zweite Thread, der den Mutex erwirbt, angehalten, bis der erste Thread den Mutex freigibt.
Mutex eignet sich sehr gut zur Realisierung dieser Funktion, aber gibt es einen einfacheren Weg? Das ist AutoResetEvent: Threads können durch Signalisierung miteinander kommunizieren. In der Regel handelt es sich bei dieser Kommunikation um Ressourcen, auf die der Thread exklusiven Zugriff benötigt. Das Wichtigste ist, dass es eine Kommunikationsmethode zwischen Threads bietet, sodass die Aufrufschritte des Threads flexibler gesteuert werden können. Wir verwenden eine Semaphore.
Code:
Namensraum LoginBase
{
öffentliches Klassenregister
{
XmppClientConnection_connection;
static AutoResetEvent myResetEvent;
öffentlicher Bool IsUsed;
publicRegister()
{
_connection = new XmppClientConnection();
_connection.SocketConnectionType = agsXMPP.net.SocketConnectionType.Direct;
_connection.OnLogin += new ObjectHandler(XmppCon_OnLogin);
_connection.OnRegisterError += new OnXmppErrorHandler(XmppCon_OnRegErr);
_connection.OnRegistered += new ObjectHandler(XmppCon_OnRegistered
}
public bool IsSuccessfull = false;
public void RegisterJab(string Benutzername, string Passwort, string server)
{
_connection.Server = server;
_connection.Username = Benutzername;
_connection.Password = Passwort;
_connection.Port = 80;
_connection.UseSSL = false;
_connection.AutoResolveConnectServer = true;
_connection.ConnectServer = null;
_connection.SocketConnectionType = agsXMPP.net.SocketConnectionType.Direct;
_connection.UseStartTLS = true;
_connection.RegisterAccount = true;
myResetEvent = new AutoResetEvent(false);
_connection.Open();
myResetEvent.WaitOne(20 * 1000, true);
_connection.Close()
;
private void XmppCon_OnRegistered(object sender)
{
IsSuccessfull = true;
myResetEvent.Set();
}
private void XmppCon_OnLogin(object sender)
{
IsSuccessfull = true;
myResetEvent.Set();
}
private void XmppCon_OnRegErr(object sender, Element e)
{
//Wenn errCode 409 ist, existiert der Benutzer bereits
IsSuccessfull = false;
Element xn = e.SelectSingleElement("error");
if (xn.Attribute("code") == "409")
IsUsed = true;
myResetEvent.Set()
;
}
}
Stellen Sie es zunächst auf einen nicht beendeten Status ein, geben Sie dann den Jabber-Thread ein, blockieren Sie den Asp-Thread und warten Sie. Das Timeout beträgt 20 Sekunden. Wenn das Callback-Ereignis ausgelöst wird, wird der Status auf beendet gesetzt und der ASP-Thread setzt die Ausführung fort.
Die Synchronisierung wurde erfolgreich abgeschlossen, sodass der Asp-Thread erst fortgesetzt wird, wenn die Ausführung des Jabber-Hilfsthreads abgeschlossen ist.
http://www.cnblogs.com/bluewater/archive/2006/08/14/476720.html