2010-10-05 68 views
2

我有一个silverlight客户端与服务器上的Web服务进行通信。它有一个DoSomething方法,它什么都不做,并且返回void。Silverlight Web服务回调性能

在客户端,我调用服务,并听取当响应回来:

proxy.OnDoSomethingCompleted+=OnDoSomethingCompleted; 
t0 = Environment.TickCount; 
proxy.DoSomethingAsync(); 

void DoSomething(..) 
{ 
    t1 = Environment.TickCount; 
} 

网络捕获指示响应2ms的内发回。但是,OnDoSomethingCompleted直到80ms后才会被调用。回调执行时有没有办法改变?

+1

是UI线程上执行的回调? – Gabe 2010-10-05 15:28:55

+0

显示代码OnDoSomethingCompleted。 – AnthonyWJones 2010-10-05 16:20:10

+0

DoSomethingAsync()在工作线程中调用。回调DoSomething()也在(不同的)工作线程中执行。 – Metro 2010-10-05 19:36:30

回答

0

通常情况下,OnDoSomethingCompleted()将UI线程,即在被执行时,幕后的东西是调用一些代码(在概念上)看起来有点像这样:

Dispatcher.BeginInvoke(() => OnDoSomethingCompleted()); 

这意味着OnDoSomethingCompleted( )在UI线程决定合作并运行之前不会执行。大多数时间没问题,但有时候你希望它运行得更快。基本的方法是使用线程池进行原始调用,这意味着响应将从同一个线程池(不一定在同一个线程上)处理。如果你可以在这个返回方法中做一些真正的处理,并且不只是自动将它们编组回到UI线程,这可以加快你的处理速度。

托梅克(从MS WCF小组)给出了如何在这里做一个很好的例子:

http://tomasz.janczuk.org/2009/08/improving-performance-of-concurrent-wcf.html

这也是我的理解,对于WCF连接的同步情况下被设定,当你第一次打开它。这意味着无论第一次打开WCF连接的线程是处理所有稍后调用的线程。因此,在我自己的代码,我做这样的事情:

// Spin up the connection on a new worker thread. 
// According to Tomek, this will cause all WCF calls to be made from this thread. 
ManualResetEvent resetEvent = new ManualResetEvent(false); 
wcfWorkerThread = new Thread(new ThreadStart(() => InitializeNotificationClient(resetEvent))); 
wcfWorkerThread.Name = "WcfWorkerThread"; 
wcfWorkerThread.Start(); 
resetEvent.WaitOne(); 

然后InitializeNotificationClient()看起来是这样的:

private void InitializeNotificationClient(ManualResetEvent resetEvent = null) 
{ 
    try 
    { 
     notificationClient = GetRoomServiceClient(); 
     notificationClient.OpenAsync(callback); 
     notificationClient.InnerChannel.Faulted += new EventHandler(Channel_Faulted); 
     notificationClient.InnerChannel.Closed += new EventHandler(Channel_Closed); 
    } 
    finally 
    { 
     // Tell the waiting thread that we're ready. 
     if (resetEvent != null) 
     { 
      resetEvent.Set(); 
     } 
    } 
} 
+0

该回调已在工作线程上执行。此博客显示使用并发Web服务调用时的性能改进。每次通话的持续时间仍然相同,因此如果必须按顺序执行呼叫(例如,当第一个呼叫的结果输入到第二个呼叫时),则不会有任何改进 – Metro 2010-10-05 20:39:28

+0

您是使用Net.TCP还是BasicHttpBinding作为默认值?如果你关注性能,Net.TCP显然是一个很好的选择。但是,如果您有使用HTTP的其他原因,则可能需要查看使用WebRequest.RegisterPrefix()切换到Silverlight HTTP堆栈(而不是浏览器)。这应该是更快,但我没有自己计时。 http://msdn.microsoft.com/en-us/library/dd920295(VS.95).aspx – 2010-10-05 22:40:20

+0

另外,还有一件事。您需要确保您从单独的工作线程打开连接。根据Tomek的说法(从我们的谈话中),从特定线程打开连接将导致所有稍后的WCF调用被封送到该线程。看到我的(编辑)答案的一些代码。 – 2010-10-06 15:41:18