How do you know when an asynchronous call actually starts?

I want to be able to measure the time it takes to execute an asynchronous method.

When I call the method synchronously, I run the following code and get the exact amount of time that the MyMethod method took.

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

      

I changed my code to execute MyMethod asynchronously, so now my code looks like this.

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

      

The problem is that the stopwatches do not measure the time it takes to complete the request any longer. They measure the time from when a request is entered into the ThreadPool queue until the end of the call. Thus, I finish the list of stopwatches with a linear increase in time.

How do I fix my stopwatches? Is there a way to know when the request starts?

Thank!

UPDATE: I cannot change the implementation of MyMethod.

+2


source to share


3 answers


Create a BeginTimedMyMethod method, not in the webservice class. In the BeginTimedMyMethod implementation, call the intermediate method instead of MyMethod, which is called asynchronously. Start the stopwatch there, then call MyMethod.



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

void StartTimedMethod(Request request)
{
    stopWatches[i].Start();
    webservice.MyMethod(request);
}

      

+1


source


What exactly are you trying to do with measurements? Like you, you measure the actual amount of time it takes when you ask for a job to be done when it is completed. This seems to make sense. Both before and after your code switch, you measure the actual request latency.



0


source


It looks like you are trying to set up an aspect around the mymethod class. The easiest way to do this would be with an AOP framework like PostSharp. That you create something in strings

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

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

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

      

Then, inside your class with your method, you

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

      

This will allow you to bind that aspect to a method without having to change the method. However, you will still have to recompile the code there. So this should be viable even if this class is just a proxy for an external service that you have no control over, as you should just sit in that aspect on the proxy.

0


source







All Articles