在Asp.net中調用非同步方法呼叫-使用訊號量

來源:互聯網
上載者:User

有些庫可能只提供了非同步方法呼叫,而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線程才會繼續下去。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.