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.