Algumas bibliotecas podem fornecer apenas métodos assíncronos, mas o ASP.net é realmente síncrono. Desta vez, encontramos um problema: a função de retorno de chamada não será executada até que a página seja exibida. E o processo que preciso é: realizar a verificação na função de retorno de chamada antes que a página possa ser renderizada. Mutex e AutoResetEvent fornecem métodos para coordenar as etapas de execução do thread por meio de semáforos.
XmppClientConnection é uma classe da biblioteca agsxmppJabber. Chamar Open retornará imediatamente ao cliente (ou seja) para renderizar a página, independentemente de ser bem-sucedido ou não. Ao mesmo tempo, outro thread executará as operações de login e nova conta. Após o sucesso, o evento de retorno de chamada será acionado, portanto O retorno de chamada será executado somente após a renderização da página, o que não está de acordo com a lógica que desejamos. Chamamos o thread que chama Open: thread Jabber, e o thread que realiza o login: thread auxiliar do thread Jabber.
Minha ideia inicial era usar o Monitor, código:
objeto privado objlock=novo objeto();
public void RegisterJab (string nome de usuário, string senha, string servidor)
{
_connection.Server = servidor;
_conexão.Nome de usuário = nome de usuário;
_conexão.Senha = senha;
_conexão.Porta = 80;
_connection.UseSSL = falso;
_connection.AutoResolveConnectServer = verdadeiro;
_connection.ConnectServer = nulo;
_connection.SocketConnectionType = agsXMPP.net.SocketConnectionType.Direct;
_connection.UseStartTLS = verdadeiro;
_connection.RegisterAccount = verdadeiro;
Moniter.Enter(objlock);
_conexão.Open();
Moniter.Wait(objlock);
_conexão.Fechar()
;
private void XmppCon_OnRegistered (remetente do objeto)
{
ÉSucesso = verdadeiro;
Moniter.Exit(objlock);
}
Uma exceção será lançada ao executar Monitor.Exit(): SynchronizationLockException, porque o thread auxiliar do Jabber não é o proprietário do bloqueio. Verifica-se que o Monitor é como uma seção crítica e não é adequado para lidar com esta situação.
Posteriormente, movido para Mutex, Mutex: é uma primitiva de sincronização que concede acesso exclusivo a um recurso compartilhado para apenas um thread. Se um thread adquirir um mutex, o segundo thread a adquirir o mutex será suspenso até que o primeiro thread libere o mutex.
Mutex é muito adequado para realizar esta função, mas existe uma maneira mais fácil? Isso é AutoResetEvent: permitir que threads se comuniquem entre si por meio de sinalização. Normalmente, esta comunicação envolve recursos aos quais o thread necessita de acesso exclusivo. O mais importante é que ele fornece um método de comunicação entre threads, para que as etapas de chamada do thread possam ser controladas de forma mais flexível. O que usamos é um semáforo.
Código:
namespace LoginBase
{
classe pública Registrar
{
XmppClientConnection_connection;
static AutoResetEvent myResetEvent;
bool público IsUsed;
registro público()
{
_connection = new XmppClientConnection();
_connection.SocketConnectionType = agsXMPP.net.SocketConnectionType.Direct;
_connection.OnLogin += novo ObjectHandler(XmppCon_OnLogin);
_connection.OnRegisterError += novo OnXmppErrorHandler(XmppCon_OnRegErr);
_connection.OnRegistered += novo ObjectHandler(XmppCon_OnRegistered })
;
public bool IsSuccessfull = falso;
public void RegisterJab (string nome de usuário, string senha, string servidor)
{
_connection.Server = servidor;
_conexão.Nome de usuário = nome de usuário;
_conexão.Senha = senha;
_conexão.Porta = 80;
_connection.UseSSL = falso;
_connection.AutoResolveConnectServer = verdadeiro;
_connection.ConnectServer = nulo;
_connection.SocketConnectionType = agsXMPP.net.SocketConnectionType.Direct;
_connection.UseStartTLS = verdadeiro;
_connection.RegisterAccount = verdadeiro;
meuResetEvent = novo AutoResetEvent(falso);
_conexão.Open();
myResetEvent.WaitOne(20 * 1000, verdadeiro);
_conexão.Fechar()
;
private void XmppCon_OnRegistered (remetente do objeto)
{
ÉSucesso = verdadeiro;
meuResetEvent.Set();
}
private void XmppCon_OnLogin (remetente do objeto)
{
ÉSucesso = verdadeiro;
meuResetEvent.Set();
}
private void XmppCon_OnRegErr (objeto remetente, elemento e)
{
//Se errCode for 409, o usuário já existe
ÉSucesso = falso;
Elemento xn = e.SelectSingleElement("erro");
if (xn.Attribute("código") == "409")
ÉUsado = verdadeiro;
meuResetEvent.Set()
;
}
}
Primeiro, defina-o para um estado não encerrado, depois entre no thread Jabber, bloqueie o thread Asp e aguarde. O tempo limite é de 20 segundos. Se o evento de retorno de chamada for acionado, o status será definido como encerrado e o thread asp continuará a execução.
A sincronização foi concluída com êxito, de modo que o thread Asp não continuará até que o thread auxiliar do Jabber termine de ser executado.
http://www.cnblogs.com/bluewater/archive/2006/08/14/476720.html