从Silverlight 3应用程序同步调用Web服务?

问题描述:

我想重用一些.NET代码来执行一些调用数据访问层类型的服务。我已经设法将方法的输入和方法的输出打包,但不幸的是该服务是从内部代码调用的,我真的不想为了异步而重写。从Silverlight 3应用程序同步调用Web服务?

不幸的是,Silverlight中生成的web服务代码只生成异步方法,所以我想知道是否有人有工作代码设法解决这个问题?

注意:我不需要在本地执行的UI线程的主代码路径,但有问题的代码会想到调用它使数据访问层在本质上同步的,但整个作业可以主要在后台线程上执行。

我尝试了这里找到的配方:The Easy Way To Synchronously Call WCF Services In Silverlight,但不幸的是,它超时并且从未完成调用。

或者更确切地说,似乎发生的是完成的事件处理程序被调用,但只有在方法返回后。我怀疑事件处理程序是从调度程序或类似程序调用的,因为我在这里阻塞了主线程,所以直到代码实际返回到GUI循环时才会完成。

或类似的东西。

这是我自己的版本,我写之前,我发现上面的食谱,但它从同一个问题的困扰:

public static object ExecuteRequestOnServer(Type dalInterfaceType, string methodName, object[] arguments) 
{ 
    string securityToken = "DUMMYTOKEN"; 
    string input = "DUMMYINPUT"; 
    object result = null; 
    Exception resultException = null; 
    object evtLock = new object(); 

    var evt = new System.Threading.ManualResetEvent(false); 
    try 
    { 
     var client = new MinGatServices.DataAccessLayerServiceSoapClient(); 
     client.ExecuteRequestCompleted += (s, e) => 
     { 
      resultException = e.Error; 
      result = e.Result; 
      lock (evtLock) 
      { 
       if (evt != null) 
        evt.Set(); 
      } 
     }; 
     client.ExecuteRequestAsync(securityToken, input); 
     try 
     { 
      var didComplete = evt.WaitOne(10000); 
      if (!didComplete) 
       throw new TimeoutException("A data access layer web service request timed out (" + dalInterfaceType.Name + "." + methodName + ")"); 
     } 
     finally 
     { 
      client.CloseAsync(); 
     } 
    } 
    finally 
    { 
     lock (evtLock) 
     { 
      evt.Close(); 
      evt = null; 
     } 
    } 

    if (resultException != null) 
     throw resultException; 
    else 
     return result; 
} 

基本上都食谱做到这一点:

  • 设置一个ManualResetEvent的
  • 钩入Completed事件
  • 事件处理函数从服务调用中获取结果,并通知事件
  • 主线程现在启动Web服务调用异步
  • 然后等待该事件成为信号

然而,事件处理函数不是调用,直到上面的方法又回来了,因此我的代码检查对于evt != null等,以避免TargetInvocationException在方法超时后终止我的程序。

有谁知道:

  • ...如果有可能在Silverlight 3
  • 在所有...我已经错了上面做了什么?

我怀疑MinGatServices啄正试图通过确保ExecuteRequestCompleted在主UI线程分派很有帮助。

我还怀疑你的代码已经在你阻塞的主UI线程上执行了。切勿在Silverlight中阻止UI线程,如果您需要阻止UI使用类似BusyIndicator控件的内容。

下跪的答案是“代码异步”,但不能满足您的问题的要求。

一个可能不太麻烦的解决方案是从任何用户操作在不同的线程上调用它的代码开始,使用BackgroundWorker

当然MinGatServices可能确保回调发生时执行在这种情况下,你需要得到这在不同的线程运行ExecuteRequestAsync在同一个线程(跳回到UI线程是可以接受的): -

Deployment.Current.Dispatcher.BeginInvoke(() => client.ExecuteRequestAsync(securityToken, input)); 
+0

我会尝试这一点,MinGatServices名字只是一个命名空间,类基本上只包含方法等等诸如此类的陷阱我已经奠定了自己的问题都是可见的问题,但肯定的,我确实执行了在UI线程上调用这个的主代码,所以我会尝试在这里分割执行路径。但是,我应该理解你的答案,“service.MethodNameAsync”通过Dispatcher类在UI线程上运行吗?所以,既然我从UI线程调用了这个,我现在有UI线程等待UI线程? – 2010-05-28 12:46:07

+0

@Lasse:嗯,__if__异步方法试图有帮助,那么它将使用Dispatcher为线程排队要在线程上执行的代码。所以,你最终会遇到这种僵局。 – AnthonyWJones 2010-05-28 16:37:01