Home > other >  Asynchronous QueryQueuedBuilds
Asynchronous QueryQueuedBuilds

Time:01-22

Our program uses the QueryQueuedBuilds from Microsoft.TeamFoundation.Build.Server to get all the queued builds from our build server.

So far we did it synchrone from a DispatcherTimer tick method, but the UI gets non-responsive sometimes for more than 1000 ms. This is the original call:

    public List<QueuedBuild> GetQueuedBuilds()
    {
        List<QueuedBuild> queuedBuilds = new List<QueuedBuild>();

        foreach (var project in _teamProjectList)
        {
            IQueuedBuildSpec queuedBuildSpec = _buildServer.CreateBuildQueueSpec(project.Name);
            IQueuedBuildQueryResult queuedBuildQueryResult = _buildServer.QueryQueuedBuilds(queuedBuildSpec);

            if (queuedBuildQueryResult.QueuedBuilds.Length > 0)
            {
                foreach (var result in queuedBuildQueryResult.QueuedBuilds)
                {
                    queuedBuilds.Add(new QueuedBuild()
                    {
                     // Set properties from result
                    });
                }
            }                
        }

        return queuedBuilds;
    }

But the line with the QueryQueuedBuilds takes a long time.

I discovered there are asynchronous methods BeginQueryQueuedBuilds and EndQueryQueuedBuilds, but I cannot find examples how to use it. This is what I got so far:

public List<QueuedBuild> GetQueuedBuilds()
{
    List<QueuedBuild> queuedBuilds = new List<QueuedBuild>();
    Collection<IQueuedBuildSpec> queuedBuildSpecs = new Collection<IQueuedBuildSpec>();

    foreach (var project in _teamProjectList)
    {
        queuedBuildSpecs.Add(_buildServer.CreateBuildQueueSpec(project.Name));
    }

    IAsyncResult asyncResult = _buildServer.BeginQueryQueuedBuilds(queuedBuildSpecs.ToArray(),
        OnBeginQueryQueuedBuilds, queuedBuilds);
    
    // What to do with asyncResult?

    return queuedBuilds; // How to return queuedBuilds?
}

private void OnBeginQueryQueuedBuilds(IAsyncResult ar)
{
    if (!(ar.AsyncState is List<QueuedBuild> queuedBuilds))
    {
        return;
    }

    IQueuedBuildQueryResult[] queryResults = _buildServer.EndQueryQueuedBuilds(ar);

    foreach (var queuedBuildQueryResult in queryResults)
    {
        foreach (var result in queuedBuildQueryResult.QueuedBuilds)
        {
            queuedBuilds.Add(new QueuedBuild()
            {
                // Set properties from result
            });
        }
    }

    // How to get the queuedBuilds back to the GUI?
}

The callback method works. But how do I get the queuedBuilds back to my GUI?

CodePudding user response:

I finally solved the puzzle similar to this solution.

Most important changes I did: The callback method isn't used anymore. The IAsyncResult is now passed to a Task.Factory.FromAsync() method and the task is awaited.

This is what I ended up with:

    public async Task<List<QueuedBuild>> GetQueuedBuilds()
    {
        Collection<IQueuedBuildSpec> queuedBuildSpecs = new Collection<IQueuedBuildSpec>();

        foreach (var project in _teamProjectList)
        {
            queuedBuildSpecs.Add(_buildServer.CreateBuildQueueSpec(project.Name));
        }

        IAsyncResult asyncResult = _buildServer.BeginQueryQueuedBuilds(queuedBuildSpecs.ToArray(), null, null);

        var task = Task.Factory.FromAsync(asyncResult, _buildServer.EndQueryQueuedBuilds);
        IQueuedBuildQueryResult[] queuedBuildQueryResults = await task;
        return FinishQueryQueuedBuilds(queuedBuildQueryResults);
    }

    private List<QueuedBuild> FinishQueryQueuedBuilds(IQueuedBuildQueryResult[] queuedBuildQueryResults)
    {
        List<QueuedBuild> queuedBuilds = new List<QueuedBuild>();

        foreach (var queuedBuildQueryResult in queuedBuildQueryResults)
        {
            foreach (var result in queuedBuildQueryResult.QueuedBuilds)
            {
                queuedBuilds.Add(new QueuedBuild()
                {
                    // Set properties from result
                });
            }
        }

        return queuedBuilds;
    }

I hope this can help someone else with a similar problem.

  •  Tags:  
  • Related