Как узнать, когда действительно начинается асинхронный вызов? - PullRequest
2 голосов
/ 26 октября 2009

Я хочу иметь возможность измерить время, необходимое для выполнения асинхронного метода.

Когда я вызываю метод синхронно, я запускаю следующий код и получаю точное количество времени, необходимое для метода MyMethod.

for (int i = 0; i < 5000; i++) {
    stopWatches[i].Start();
    webService.MyMethod(new Request());
    stopWatches[i].Stop();
}

Я изменил свой код для асинхронного выполнения MyMethod, поэтому теперь мой код выглядит следующим образом.

var callback = new Action<IAsyncResult>(ar => {
    int i = (int)ar.AsyncState;

    try {
        var response = webService.EndMyMethod(ar);
        stopWatches[i].Stop();
    }
}

for (int i = 0; i < 5000; i++) {
    webService.BeginMyMethod(new Request(), new AsyncCallback(callback), i);
    stopWatches[i].Start();
}

Проблема в том, что секундомеры больше не измеряют время, необходимое для выполнения запроса. Они измеряют время с момента, когда запрос поступил в очередь ThreadPool, до окончания вызова. В итоге я получаю список секундомеров с линейным увеличением времени.

Как мне починить секундомеры? Есть ли способ точно узнать, когда начинается запрос?

Спасибо!

ОБНОВЛЕНИЕ: я не могу изменить реализацию MyMethod.

Ответы [ 3 ]

1 голос
/ 28 октября 2009

Создайте метод BeginTimedMyMethod, отсутствующий в классе веб-сервиса. В реализации BeginTimedMyMethod вызовите промежуточный метод вместо MyMethod, который вызывается асинхронно. Запустите там секундомер, затем вызовите MyMethod.

void BeginTimedMyMethod(...)
{
    //create delegate with StartMethod as target
    //Invoke StartMethod delegate
}

void StartTimedMethod(Request request)
{
    stopWatches[i].Start();
    webservice.MyMethod(request);
}
0 голосов
/ 26 октября 2009

То, что вы пытаетесь сделать, это настроить аспект вокруг класса mymethod. Самый простой способ сделать это - использовать AOP-фреймворк, такой как PostSharp. Что вы создаете что-то вроде

public class MyStopWatchContext
{
    Stopwatch _watch = new Stopwatch();

    public void OnMethodEntry()
    {
        _watch.Start();
    }

    public void OnMethodExit()
    {
        _watch.End();
        Debug.Print(_watch.Duration);
    }
}

Тогда внутри вашего класса с вашим методом у вас есть

public class MyService
{
    [MyStopWatchContext]
    public void SomeServiceMethod()
    { ...
    }
}

Это позволит вам связать этот аспект с методом без необходимости изменять метод. Однако вам все равно нужно будет иметь возможность перекомпилировать код там. Так что это должно быть жизнеспособным, даже если этот класс является просто прокси для внешней службы, которую вы не можете контролировать, поскольку вы должны иметь возможность просто разместить этот аспект поверх прокси-вызова.

0 голосов
/ 26 октября 2009

Что именно вы пытаетесь сделать с измерениями? Как и вы, вы измеряете фактическое количество времени, которое требуется, когда вы запрашиваете некоторую работу, чтобы быть выполненным, когда это будет завершено. Кажется, это имеет смысл. Как до, так и после переключения кода вы измеряете фактическую задержку запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...