如何强制异步Web服务调用充当同步?

问题描述:

我遇到的问题是一些已移植到Silverlight应用程序的asmx Web服务。问题是silverlight上的asmx服务只允许异步方法调用。大多数情况下这是可以接受的,但有一个例子我真的不想要它。如何强制异步Web服务调用充当同步?

在每个Web调用块开始时,都会调用全局函数CheckTimeout。它所做的就是调用Web方法来查看用户的登录令牌是否已过期,如果有,说明用户已超时并请重新登录。问题是,我希望CheckTimeout在返回之前完全结束。调用方法知道你在做各种事情之前仍然登录。

我试过在CheckTimeout中使用EventWaitHandler,该方法接收来自服务器的异步结果会发出信号,但我想这里真的只有一个线程工作,因为如果我这样做,请求甚至不会发送到Web服务器那样。关于我如何做我想要做的事情的任何想法?

private static EventWaitHandle wait_for_check_login = new AutoResetEvent(false); 

    private static bool check_timeout_result = false; 

    public static void CheckTimeout() 
    { 
     rji_ws.CheckLoginAsync(login_key); 

     wait_for_check_login.WaitOne(); 

     if (check_timeout_result) 
      { 
       check_timeout_result = false; 
       return; 
      } 
      else 
      { 
       MessageBox.Show("You've timed out after a period of inactivity. Please log in again"); 
       login_key = Guid.Empty; 
       System.Windows.Browser.HtmlPage.Document.Submit(); 
      } 


    } 

    private static void CheckTimeoutResults(object sender, RJI_WS.CheckLoginCompletedEventArgs e) 
    { 
     if (e.Error != null) 
     { 
      //MessageBox.Show("There was an error communicating with the server 
      wait_for_check_login.Set(); 
     } 
     else 
     { 
      check_timeout_result = e.Result; 
      wait_for_check_login.Set(); 


     } 
    } 

如果调用没有将它传递给服务器,问题可能是您错过了CheckLoginAsync代码中的某些内容(您没有发布它)。

在任何情况下,以这种方式编写代码将阻止主UI线程。您最好以下列方式安排您的代码:

/// Usage: 
/// CheckLoginThen((bool result) => { CallWebServices(); }); 
void CheckLoginThen(Action<bool> a) 
{ 
    rji_ws.CheckLoginAsync(login_key, 
    (sender, e) => 
    { 
     if (e.Error != null) 
     { 
     MessageBox.Show("There was an error communicating with the server"); 
     } 
     else 
     { 
     var result = e.Result; 
     a(result); 
     } 
    }, 
    null); 
} 

把代码放到一个单独的方法(如果它不是在一个的话)并调用从处理程序checklogin服务完成。