【问题标题】:Silverlight web service callback performanceSilverlight Web 服务回调性能
【发布时间】:2010-10-06 23:46:55
【问题描述】:

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

在客户端,我调用服务并监听响应何时返回:

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

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

网络捕获表明响应在 2 毫秒内被发回。但是,直到 80 毫秒后才会调用 OnDoSomethingCompleted。有没有办法改变回调何时执行?

【问题讨论】:

  • 回调是否在UI线程上执行?
  • 显示代码 OnDoSomethingCompleted。
  • DoSomethingAsync() 在工作线程中被调用。回调 DoSomething() 也在(不同的)工作线程中执行。

标签: silverlight performance service callback


【解决方案1】:

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

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

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

Tomek(来自 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();
         }
     }
 }

【讨论】:

  • 回调已经在工作线程上执行。此博客展示了使用并发 Web 服务调用时的性能改进。每次调用的持续时间仍然相同,因此如果必须按顺序进行调用(例如,当第一次调用的结果输入到第二次调用时),则不会有任何改进
  • 您使用的是 Net.TCP,还是默认的 BasicHttpBinding?如果您关心性能,Net.TCP 显然是要走的路。但是,如果您有其他使用 HTTP 的原因,您可能需要考虑使用 WebRequest.RegisterPrefix() 来切换到 Silverlight HTTP 堆栈(而不是浏览器的堆栈)。据说速度更快,虽然我自己没有计时。 msdn.microsoft.com/en-us/library/dd920295(VS.95).aspx
  • 另外,还有一件事。您需要确保从单独的工作线程打开连接。根据 Tomek 的说法(来自我们的一次对话),从特定线程打开连接将导致所有以后的 WCF 调用都被编组到该线程。有关某些代码,请参阅我的(已编辑)答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多