异步 QueryQueuedBuilds
Asynchronous QueryQueuedBuilds
我们的程序使用 Microsoft.TeamFoundation.Build.Server 中的 QueryQueuedBuilds 从我们的构建服务器获取所有排队的构建。
到目前为止,我们是通过 DispatcherTimer tick 方法同步的,但 UI 有时会超过 1000 毫秒没有响应。这是原始调用:
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;
}
但 QueryQueuedBuilds 的行需要很长时间。
我发现有异步方法 BeginQueryQueuedBuilds 和 EndQueryQueuedBuilds,但我找不到如何使用它的示例。这是我到目前为止得到的:
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?
}
回调方法有效。但是如何让 queuedBuilds 回到我的 GUI?
我终于解决了类似于this解决方案的难题。
我所做的最重要的改变:
不再使用回调方法。
IAsyncResult
现在被传递给 Task.Factory.FromAsync()
方法并等待任务。
这就是我最终得到的结果:
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;
}
我希望这可以帮助遇到类似问题的其他人。
我们的程序使用 Microsoft.TeamFoundation.Build.Server 中的 QueryQueuedBuilds 从我们的构建服务器获取所有排队的构建。
到目前为止,我们是通过 DispatcherTimer tick 方法同步的,但 UI 有时会超过 1000 毫秒没有响应。这是原始调用:
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;
}
但 QueryQueuedBuilds 的行需要很长时间。
我发现有异步方法 BeginQueryQueuedBuilds 和 EndQueryQueuedBuilds,但我找不到如何使用它的示例。这是我到目前为止得到的:
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?
}
回调方法有效。但是如何让 queuedBuilds 回到我的 GUI?
我终于解决了类似于this解决方案的难题。
我所做的最重要的改变:
不再使用回调方法。
IAsyncResult
现在被传递给 Task.Factory.FromAsync()
方法并等待任务。
这就是我最终得到的结果:
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;
}
我希望这可以帮助遇到类似问题的其他人。