首页 > 解决方案 > 从多个线程 C#.Net 调用时 GetWorkItemAsync 方法异常

问题描述

我正在尝试从 VSO 获取工作项的链接,当从单个线程调用时代码似乎工作正常,但在从每个循环的并行调用时抛出异常。

我在类的构造函数中初始化了我的 vso 客户端对象:

vso = new WorkItemReporting(Config.VSTSAccessToken);

然后在一个方法中:

Parallel.ForEach(msrcAbBugsToProcess, new ParallelOptions { MaxDegreeOfParallelism = 10 }, bugId =>
{
    var workItemLinks = vso.GetWorkItemSourceCodeLinks(bugId);
});

下面的 witclient 是一个 WorkItemTrackingHttpClient,它位于不同的类 (WorkItemReporting) 中并调用 API。正是这个调用失败了。

public List<string> GetWorkItemSourceCodeLinks(int bugId)
{
    var workItemSourceCodeLinks = new List<string>();         

    var workItem = _witClient.GetWorkItemAsync(bugId, null, null, WorkItemExpand.Relations).Result;
    if (workItem?.Relations != null)
    {
        var validSourceCodeLinkTypes = new List<string> { "ArtifactLink", "Hyperlink" };
        foreach (var relation in workItem.Relations)
        {
            if (validSourceCodeLinkTypes.Contains(relation.Rel))
            {
                workItemSourceCodeLinks.Add(relation.Url);
            }
        }
    }
}   

如果我不使用 Parallel.ForEach 并且我从 API 获取所需的数据,这可以正常工作。当我这样做时,我有 50% 的时间得到这个异常:

Object reference not set to an instance of an object.   
at System.Security.Cryptography.X509Certificates.X509CertificateCollection.GetHashCode()
   at System.Net.HttpWebRequest.GetConnectionGroupLine()
   at System.Net.HttpWebRequest.SubmitRequest(ServicePoint servicePoint)
   at System.Net.HttpWebRequest.BeginGetResponse(AsyncCallback callback, Object state)
   at System.Net.Http.HttpClientHandler.StartGettingResponse(RequestState state)
   at System.Net.Http.HttpClientHandler.StartRequest(Object obj)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at Microsoft.VisualStudio.Services.Common.VssHttpMessageHandler.<SendAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.Services.Common.VssHttpRetryMessageHandler.<SendAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.<SendAsync>d__48.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.<SendAsync>d__45`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.<SendAsync>d__27`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.<SendAsync>d__26`1.MoveNext()

有什么我做错了吗?

标签: c#.netazure-devopsazure-devops-rest-api

解决方案


一个解决方案是在WorkItemReporting内部创建Parallel.ForEach

Parallel.ForEach(msrcAbBugsToProcess, new ParallelOptions { MaxDegreeOfParallelism = 10 }, bugId =>
{
    var vso = new WorkItemReporting(Config.VSTSAccessToken);
    var workItemLinks = vso.GetWorkItemSourceCodeLinks(bugId);
});

推荐阅读