Как узнать, когда действительно начинается асинхронный вызов?

StackOverflow https://stackoverflow.com/questions/1626064

  •  06-07-2019
  •  | 
  •  

Вопрос

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

Когда я вызываю метод синхронно, я запускаю следующий код и получаю точное количество времени, которое потребовалось методу 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.

Это было полезно?

Решение

Создайте метод 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);
}

Другие советы

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

Похоже, вы пытаетесь настроить аспект вокруг класса mymethod.Самый простой способ сделать это — использовать среду АОП, такую ​​​​как 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()
    { ...
    }
}

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top