Я хочу иметь возможность измерить время, необходимое для выполнения асинхронного метода.
Когда я вызываю метод синхронно, я запускаю следующий код и получаю точное количество времени, которое потребовал метод 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 до конца вызова. Таким образом, я заканчиваю список секундомеров с линейным увеличением времени.
Как исправить мои секундомеры? Есть ли способ узнать, когда начинается запрос?
Спасибо!
UPDATE: я не могу изменить реализацию MyMethod.
Создайте метод BeginTimedMyMethod, а не в классе webservice. В реализации BeginTimedMyMethod вызовите промежуточный метод вместо MyMethod, который вызывается асинхронно. Запустите секундомер там, затем вызовите MyMethod.
void BeginTimedMyMethod(...)
{
//create delegate with StartMethod as target
//Invoke StartMethod delegate
}
void StartTimedMethod(Request request)
{
stopWatches[i].Start();
webservice.MyMethod(request);
}
Что именно вы пытаетесь сделать с измерениями? Как и вы, вы измеряете фактическое количество времени, которое требуется, когда вы просите, чтобы какая-либо работа была выполнена, когда она будет завершена. Кажется, это имеет смысл. Как до, так и после вашего кодового переключателя вы измеряете фактическую задержку запроса.
Похоже, что вы пытаетесь настроить аспект вокруг класса 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()
{ ...
}
}
Это позволит вам привязать этот аспект к методу без необходимости изменения метода. Однако вам все равно придется перекомпилировать код там. Таким образом, это должно быть жизнеспособным, даже если этот класс является просто прокси-сервером для внешней службы, на которую у вас нет контроля, поскольку вы должны просто сидеть в этом аспекте на прокси-сервере.