Производительность обратного вызова веб-службы Silverlight - PullRequest
2 голосов
/ 05 октября 2010

У меня есть клиент Silverlight, который связывается с веб-службой на сервере. У него есть метод DoSomething, который ничего не делает и возвращает void.

На клиенте я вызываю службу и слушаю, когда ответ возвращается:

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

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

Захват сети указывает, что ответ отправляется обратно в течение 2 мс. Однако OnDoSomethingCompleted вызывается только через 80 мс. Есть ли способ изменить время выполнения обратного вызова?

1 Ответ

0 голосов
/ 05 октября 2010

Обычно OnDoSomethingCompleted () выполняется в потоке пользовательского интерфейса, то есть за кулисами что-то вызывает некоторый код, который (концептуально) выглядит примерно так:

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

Это означает, что OnDoSomethingCompleted () не будет выполняться, пока поток пользовательского интерфейса не решит сотрудничать и запустить его. В большинстве случаев это нормально, но могут быть моменты, когда вы хотите, чтобы он работал быстрее. Основной подход заключается в использовании пула потоков для выполнения исходного вызова, что означает, что ответ будет обработан из того же пула потоков (не обязательно в одном и том же потоке). Если вы можете выполнить некоторую реальную обработку в этом методе возврата, а не просто автоматически перенаправить ее обратно в поток пользовательского интерфейса, это может несколько ускорить вашу обработку.

Томек (из команды 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();
         }
     }
 }
...