You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Graph API认证令牌重叠疑问及TaskCanceledException排查

问题背景与疑问

我们在Azure中部署了拥有全部所需权限的应用“App1”,同时运行着7个C# Windows服务实例,这些实例均使用该Azure应用连接Outlook邮箱,仅配置存在差异——每个实例对应连接一个唯一的邮箱。

疑问1:令牌是否会重叠?

各服务实例运行在独立的Windows服务器上,当所有服务执行如下认证代码时,是否会因共用Azure应用“App1”导致令牌重叠?还是因每个实例连接唯一邮箱,会获取到各自独立的访问令牌?

认证代码:

AuthenticationResult authResult = null;
GraphServiceClient graphClient = null;
IMailFolderMessagesCollectionPage inboxMessage = null;
try
{
    string tenantId = "TenantId";
    string clientId = "ClientId";
    string clientSecret = "ClientSecret";
    var authority = $"https://login.microsoftonline.com/{tenantId}";
    var app = ConfidentialClientApplicationBuilder
        .Create(clientId)
        .WithClientSecret(clientSecret)
        .WithAuthority(new Uri(authority))
        .Build();
    var scopes = new[] { "https://graph.microsoft.com/.default" };
    authResult = await app.AcquireTokenForClient(scopes).ExecuteAsync();
}
catch (Exception ex)
{
   //return;
}

if (authResult != null)
{
    graphClient = new GraphServiceClient(
    new DelegateAuthenticationProvider(requestMessage =>
    {
        requestMessage.Headers.Authorization =
            new AuthenticationHeaderValue("bearer", authResult.AccessToken);

        return Task.FromResult(0);
    }));

疑问2:TaskCanceledException的原因?

此外,我们频繁遇到如下错误,想了解当前架构是否会影响应用,若不是,该错误的可能原因是什么?

错误日志:

Message: System.Threading.Tasks.TaskCanceledException: A task was canceled.
   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 System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Graph.HttpProvider.<SendRequestAsync>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   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 System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Graph.HttpProvider.<SendAsync>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   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 System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Graph.BaseRequest.<SendRequestAsync>d__40.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   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 System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Graph.BaseRequest.<SendAsync>d__34`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   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 System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Graph.MessageAttachmentsCollectionRequest.<GetAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   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 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at GraphPOC.EmailMain.<GetDataAsync>d__63.MoveNext()
Category: Error
Priority: -1
EventId: 0
Severity: Error
Title:
App Domain: GraphPOC.exe
ProcessId: 988
Process Name: D:\Program Files\GraphPOC.exe
Thread Name: 
Win32 ThreadId:4884
Extended Properties: 
    Callstack=   at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
   at System.Environment.get_StackTrace()
   at System.Diagnostics.TraceEventCache.get_Callstack()
   at System.Diagnostics.TraceListener.WriteFooter(TraceEventCache eventCache)
   at Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedTextWriterTraceListener.TraceData(TraceEventCache eventCache, String source, TraceEventType eventType, Int32 id, Object data)
   at Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener.TraceData(TraceEventCache eventCache, String source, TraceEventType eventType, Int32 id, Object data)
   at Microsoft.Practices.EnterpriseLibrary.Logging.LogSource.TraceData(TraceEventType eventType, Int32 id, LogEntry logEntry, TraceListenerFilter traceListenerFilter)
   at Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter.ProcessLog(LogEntry log)
   at Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter.Write(LogEntry log)
   at GraphPOC.EmailMain.<GetDataAsync>d__63.MoveNext()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run()
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining, Task& currentTask)
   at System.Threading.Tasks.Task.FinishContinuations()
   at System.Threading.Tasks.Task`1.TrySetCanceled(CancellationToken tokenToRecord, Object cancellationException)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetException(Exception exception)
   at Microsoft.Graph.MessageAttachmentsCollectionRequest.<GetAsync>d__3.MoveNext()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run()
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining, Task& currentTask)
   at System.Threading.Tasks.Task.FinishContinuations()
   at System.Threading.Tasks.Task`1.TrySetCanceled(CancellationToken tokenToRecord, Object cancellationException)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetException(Exception exception)
   at Microsoft.Graph.BaseRequest.<SendAsync>d__34`1.MoveNext()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run()
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining, Task& currentTask)
   at System.Threading.Tasks.Task.FinishContinuations()
   at System.Threading.Tasks.Task`1.TrySetCanceled(CancellationToken tokenToRecord, Object cancellationException)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetException(Exception exception)
   at Microsoft.Graph.BaseRequest.<SendRequestAsync>d__40.MoveNext()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run()
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining, Task& currentTask)
   at System.Threading.Tasks.Task.FinishContinuations()
   at System.Threading.Tasks.Task`1.TrySetCanceled(CancellationToken tokenToRecord, Object cancellationException)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetException(Exception exception)
   at Microsoft.Graph.HttpProvider.<SendAsync>d__18.MoveNext()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run()
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining, Task& currentTask)
   at System.Threading.Tasks.Task.FinishContinuations()
   at System.Threading.Tasks.Task`1.TrySetCanceled(CancellationToken tokenToRecord, Object cancellationException)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetException(Exception exception)
   at Microsoft.Graph.HttpProvider.<SendRequestAsync>d__19.MoveNext()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run()
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining, Task& currentTask)
   at System.Threading.Tasks.Task.FinishContinuations()
   at System.Threading.Tasks.Task`1.TrySetCanceled(CancellationToken tokenToRecord, Object cancellationException)
   at System.Threading.Tasks.Task`1.TrySetCanceled(CancellationToken tokenToRecord)
   at System.Threading.Tasks.TaskCompletionSource`1.TrySetCanceled(CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.SetTaskCanceled(HttpRequestMessage request, CancellationTokenSource cancellationTokenSource, TaskCompletionSource`1 tcs)
   at System.Net.Http.HttpClient.<>c__DisplayClass59_0.<StartContentBuffering>b__0(Task contentTask)
   at System.Threading.Tasks.Task.Execute()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
   at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution)
   at System.Threading.Tasks.ThreadPoolTaskScheduler.TryExecuteTaskInline(Task task, Boolean taskWasPreviouslyQueued)
   at System.Threading.Tasks.TaskScheduler.TryRunInline(Task task, Boolean taskWasPreviouslyQueued)
   at System.Threading.Tasks.TaskContinuation.InlineIfPossibleOrElseQueue(Task task, Boolean needsProtection)
   at System.Threading.Tasks.Task.FinishContinuations()
   at System.Threading.Tasks.Task.Finish(Boolean bUserDelegateExecuted)
   at System.Threading.Tasks.Task`1.TrySetException(Object exceptionObject)
   at System.Threading.Tasks.TaskCompletionSource`1.TrySetException(Exception exception)
   at System.Net.Http.HttpContent.<>c__DisplayClass21_0.<LoadIntoBufferAsync>b__0(Task copyTask)
   at System.Threading.Tasks.Task.Execute()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
   at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution)
   at System.Threading.Tasks.ThreadPoolTaskScheduler.TryExecuteTaskInline(Task task, Boolean taskWasPreviouslyQueued)
   at System.Threading.Tasks.TaskScheduler.TryRunInline(Task task, Boolean taskWasPreviouslyQueued)
   at System.Threading.Tasks.TaskContinuation.InlineIfPossibleOrElseQueue(Task task, Boolean needsProtection)
   at System.Threading.Tasks.Task.FinishContinuations()
   at System.Threading.Tasks.Task.Finish(Boolean bUserDelegateExecuted)
   at System.Threading.Tasks.Task`1.TrySetException(Object exceptionObject)
   at System.Threading.Tasks.TaskCompletionSource`1.TrySetException(Exception exception)
   at System.Net.Http.StreamToStreamCopy.BufferReadCallback(IAsyncResult ar)
   at System.IO.Compression.DeflateStreamAsyncResult.Complete(Object result)
   at System.IO.Compression.DeflateStream.ReadCallback(IAsyncResult baseStreamResult)
   at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
   at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
   at System.Net.ChunkParser.ReadCallback(IAsyncResult ar)
   at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
   at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
   at System.Net.FixedSizeReader.ReadCallback(IAsyncResult transportResult)
   at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.ContextAwareResult.Complete(IntPtr userToken)
   at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
   at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

解答

关于令牌重叠问题

不会出现令牌重叠的情况,每个服务实例都会获取到独立的访问令牌,原因如下:

  • 你使用的是客户端凭据流(Client Credentials Flow),调用AcquireTokenForClient获取的令牌基于应用身份(App1)颁发,而非用户身份。但每个服务实例是独立运行的进程,各自维护自己的令牌获取和缓存逻辑,实例之间不会共享令牌。
  • 即使所有实例共用同一个App1,每次AcquireTokenForClient调用都是独立向Azure AD发起的请求,返回的令牌是独立的(内容可能相似,但实例间无干扰)。
  • 每个实例连接不同邮箱,是在后续调用Graph API时指定目标邮箱(比如/users/{邮箱地址}/messages),令牌本身不绑定特定邮箱,只要App1拥有访问该邮箱的权限即可。

关于TaskCanceledException的原因

当前架构不会直接导致这个错误,该错误的常见原因包括:

  • 请求超时:Graph API请求超过了默认超时时间(HttpClient或GraphServiceClient默认超时通常为100秒,若网络慢或请求数据量大,易触发超时)。
  • 网络不稳定:服务器与Microsoft Graph服务之间的连接中断、延迟过高,导致请求被取消。
  • 并发请求限制:短时间内发起大量请求可能触发Microsoft Graph的限流机制,部分情况下会表现为任务取消(通常限流返回429错误,但也有例外)。
  • 代码问题:代码中手动调用了CancellationToken的取消方法,或异步操作的上下文管理不当。

排查建议

  1. 调整GraphServiceClient的超时时间,示例:
var httpClient = new HttpClient();
httpClient.Timeout = TimeSpan.FromMinutes(5); // 根据实际需求调整
var graphClient = new GraphServiceClient(httpClient, new DelegateAuthenticationProvider(...));
  1. 添加重试机制,针对网络超时或临时错误进行重试,可使用Polly等工具实现。
  2. 监控服务器网络状态,检查是否存在丢包、延迟过高的情况。
  3. 查看Microsoft Graph调用日志,确认是否有429限流错误,若有则调整请求频率。
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 13:15:31