问题
This is my code in which a list contains 2 more lists where the WorkItem
collection contains a large number of records such as 7,000 it takes 10 min
. Is there any way to make it faster and in case
it's deciding the workItem
type if it's a bug, task or product backlog item. Please tell me how to make the looping faster. It's taking 10 min to loop 7,000 records can we use threading
to make it faster?
have already Tried the parallel.for with lock the workitemlist but getting error."No Sequence found"
public void GetProjectInfo(string projectname)
{
string querystring = string.Format("select [System.Id], [System.Title],[Story.Author],[Story.Owner],[System.AssignedTo]," +
" [System.WorkItemType],[Microsoft.VSTS.Scheduling.StoryPoints],[Microsoft.VSTS.Common.Priority]," +
"[Microsoft.VSTS.Scheduling.Effort], [Actual.Effort.Completed]" +
",[System.State]," +
public void GetProjectInfo(string projectname)
"[System.IterationPath]" +
" FROM WorkItemLinks" +
" WHERE" +
" ([Source].[System.TeamProject]='{0}'" +
" and [Source].[System.WorkitemType] IN ('Feature', 'Bug', 'Product Backlog Item', 'Task')" +
")" + " and ([System.Links.LinkType]='System.LinkTypes.Hierarchy-Forward')" +
" ORDER BY [System.Id] " + " mode (Recursive)", projectname);
GetWorkItemTree(querystring);
}
private void GetWorkItemTree(string query)
{
var treeQuery = new Microsoft.TeamFoundation.WorkItemTracking.Client.Query(_workitemstore, query);
var links = treeQuery.RunLinkQuery();
var workItemIds = links.Select(l => l.TargetId).ToArray();
query = "SELECT * FROM WorkItems";
var flatQuery = new Microsoft.TeamFoundation.WorkItemTracking.Client.Query(_workitemstore, query, workItemIds);
var workItemCollection1 = flatQuery.RunQuery();
var workItemList = new List<WorkItemViewModel>();
for (int i = 0; i < workItemCollection.Count; i++)
{
var workItem = workItemCollection[i];
if (workItem.Type.Name == "Product Backlog Item")
{
var model = new WorkItemViewModel()
{
FID = (workItem.WorkItemLinks.Count > 0) ? ((workItem.WorkItemLinks[0].LinkTypeEnd.Name.ToString() != "Child") ? workItem.WorkItemLinks[0].TargetId : 0) : 0,
ID = workItem.Id,
Name = workItem.Title,
State = workItem.State,
priorty = Convert.ToInt32(workItem.Fields["Priority"].Value),
// Size =(int) workItem.Fields["Size"].Value ,
Size = Convert.ToInt32(workItem.Fields["Effort"].Value),
StoryPoints = Convert.ToInt32(workItem.Fields["Story Points"].Value),
DoneStatus = workItem.Fields["Done Status"].Value.ToString(),
StoryOwner = workItem.Fields["Story Owner"].Value.ToString(),
Assignedto = workItem.Fields["Assigned To"].Value.ToString(),
StoryAuthor = workItem.Fields["Story Author"].Value.ToString(),
IterationPath = workItem.IterationPath
};
workItemList.Add(model);
}
else
{
switch (workItem.Type.Name)
{
case "Task":
var task = new TFSTask()
{
Storyid = (workItem.WorkItemLinks.Count > 0) ? workItem.WorkItemLinks[0].TargetId : 0,
ID = workItem.Id,
name = workItem.Title,
//activity = workItem.Fields["MyCompany.Activity"].Value.ToString(),
//start = (DateTime?)workItem.Fields["MyCompany.ActivityStart"].Value,
//due = (DateTime?)workItem.Fields["MyCompany.ActivityFinish"].Value,
status = workItem.State,
IterationPath = workItem.IterationPath,
Assignedto = workItem.Fields["Assigned To"].Value.ToString(),
priorty = Convert.ToInt32(workItem.Fields["Priority"].Value),
effort = Convert.ToInt32(workItem.Fields["effort"].Value),
Completed = Convert.ToInt32(workItem.Fields["Completed"].Value)
};
if (task.Storyid != 0)
{
workItemList.Last().Tasks.Add(task);
}
break;
case "Bug":
var bug = new TFSIssue()
{
Storyid = (workItem.WorkItemLinks.Count > 0) ? workItem.WorkItemLinks[0].TargetId : 0,
ID = workItem.Id,
Name = workItem.Title,
//start = (DateTime?)workItem.Fields["MyCompany.ActivityStart"].Value,
//due = (DateTime?)workItem.Fields["MyCompany.ActivityFinish"].Value,
State = workItem.State,
IterationPath = workItem.IterationPath,
Assignedto = workItem.Fields["Assigned To"].Value.ToString(),
priorty = Convert.ToInt32(workItem.Fields["Priority"].Value),
effort = Convert.ToInt32(workItem.Fields["effort"].Value),
// Completed = Convert.ToInt32(workItem.Fields["Completed"].Value)
};
if (bug.Storyid != 0)
{
workItemList.Last().Issues.Add(bug);
}
break;
default:
break;
}
}
}
}
public class WorkItemViewModel
{
public string Name { get; set; }
public int ID { get; set; }
public string State { get; set; }
// public DateTime? due { get; set; }
public int priorty { get; set; }
public int Size { get; set; }
// public int effort { get; set; }
public int StoryPoints { get; set; }
public string DoneStatus { get; set; }
public string StoryOwner { get; set; }
public string Assignedto { get; set; }
public string StoryAuthor { get; set; }
public string IterationPath { get; set; }
public int FID { get; set; }
public List<TFSIssue> Issues { get; set; }
public List<TFSTask> Tasks { get; set; }
public WorkItemViewModel() // Added a public constructor
{
Issues = new List<TFSIssue>();
Tasks = new List<TFSTask>();
}
}
public class TFSIssue
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime? Created { get; set; }
public string State { get; set; }
public DateTime? due { get; set; }
public string IterationPath { get; set; }
public string Assignedto { get; set; }
public int priorty { get; set; }
public int effort { get; set; }
public int Storyid { get; set; }
// public int Completed { get; set; }
}
public class TFSTask
{
public int ID { get; set; }
public string name { get; set; }
// public string activity { get; set; }
public string status { get; set; }
// public DateTime? start { get; set; }
// public DateTime? due { get; set; }
public string IterationPath { get; set; }
public string Assignedto { get; set; }
public int priorty { get; set; }
public int effort { get; set; }
public int Completed { get; set; }
public int Storyid { get; set; }
}
回答1:
Try something like this:
var workItemList = new List<WorkItemViewModel>();
var t = workItemList.select(w => Task.Run(() => {
// Put the work.
}));
await Task.WhenAll(t);
回答2:
Something like this should do:
IEnumerable<Data> LoadDataFromDatabase()
{
return ...
}
void ProcessInParallel()
{
while(true)
{
var data = LoadDataFromDatabase().ToList();
if(!data.Any()) break;
data.AsParallel().ForEach(ProcessSingleData);
}
}
void ProcessSingleData(Data d)
{
// do something with data
}
回答3:
Okay, the next step is not to simply multithread this.
You've got code that's running slow, and you've used a StopWatch object to try to track down where the slowdown's occurring. Great! But, you can't stop at the 100-line-long For-Loop. Where in the For loop is the time being spent? Use the stopwatch to figure out what portion of each loop is being spent on each section, or on each line. You should be able to say, "This line here is taking 100 milliseconds each time, and over 7000 docs, that's why it's taking 10 minutes."
Right now, you're probably in the position of having either slow code or a slow algorithm/approach to the problem. You should spend effort fixing that first. Then figure out whether multithreading is going to give you good improvements.
回答4:
It seems you can use threading here,
Maybe Parallel.For can help you.
来源:https://stackoverflow.com/questions/48946160/a-list-containing-2-more-lists-works-slow-in-looping-can-i-use-thread-to-make-th