有些函式庫可能只提供了非同步方法,而ASP.net確是同步的,這次就遇到一個問題:頁面顯示出來以後才會執行回呼函數。而我需要的流程是:在回呼函數中執行驗證,然後才能呈現頁面。 Mutex,AutoResetEvent提供了一種透過信號量來協調執行緒執行步驟的方法。
XmppClientConnection是agsxmppJabber庫中的類,調用Open會立即返回客戶端(ie)呈現該頁面,而不管是否成功,同時會在另一個線程會執行登陸,新建帳戶的操作,成功後會觸發回調事件,這樣一來頁面呈現後才會執行回調,不符合我們要的邏輯。我們把呼叫Open的線程叫做:Jabber線程,把執行登陸的線程叫做:Jabber線程的輔助線程。
我最初的想法是使用Moniter,程式碼:
private object objlock=new object();
public void RegisterJab(string username, string password, string server)
{
_connection.Server = server;
_connection.Username = username;
_connection.Password = password;
_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);
}
在執行Moniter.Exit()時會拋出異常:SynchronizationLockException,因為Jabber輔助線程並不是鎖的擁有者.發現Moniter很像臨界區,並不適處理這種情況合。
後來,轉到了Mutex,Mutex: 是同步基元,它只向一個執行緒授予對共享資源的獨佔存取權。如果一個執行緒取得了互斥體,則要取得該互斥體的第二個執行緒將被掛起,直到第一個執行緒釋放該互斥體。
Mutex很合適這個功能的實現,可是還有沒有更簡單的方法呢?那就是AutoResetEvent:允許執行緒透過發送訊號互相通訊。通常,此通訊涉及執行緒需要獨佔存取的資源。最重要的是他提供了線程間通訊的方法,這樣可以更靈活的控制線程的呼叫步驟,而我們用到的就是信號量。
代碼:
namespace LoginBase
{
public class Register
{
XmppClientConnection _connection;
static AutoResetEvent myResetEvent;
public bool IsUsed;
public Register()
{
_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 username, string password, string server)
{
_connection.Server = server;
_connection.Username = username;
_connection.Password = password;
_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)
{
//errCode如果是409則已經存在用戶
IsSuccessfull = false;
Element 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