代码之家  ›  专栏  ›  技术社区  ›  Aero

HttpClient GetAsync配置Webjob处理程序

  •  1
  • Aero  · 技术社区  · 7 年前

    我正在实施一个 Azure WebJob 服务总线消息 ,执行 异步API调用 到外部web服务。执行web请求后,我的webjob和 inputMessage已被释放 在方法结束之前。 下面是一个演示问题+输出的基本示例。

    public async void HandleTestQueueMessage([ServiceBusTrigger("%TestQueue%")] BrokeredMessage inputMessage) {
        Console.WriteLine($"Received message {inputMessage.MessageId}.");
    
        Console.WriteLine("Starting web request.");
        await TestHttpClientAsync();
        Console.WriteLine("Finished web request.");
    
        await inputMessage.CompleteAsync(); // --> Exception occurs here
        Console.WriteLine($"Completed message {inputMessage.MessageId}.");
    }
    
    private async Task TestHttpClientAsync() {
        var httpClient = new HttpClient();
        var response = await httpClient.GetAsync("http://google.com");
        Console.WriteLine($"Got response, statuscode={response.StatusCode}.");
    }
    

    控制台输出:

    Executing: 'ProblemTestHandler.HandleTestQueueMessage' - Reason: 'New ServiceBus message detected on 'TestQueue'.'
    Received message a17cc4fce8c74b3c9f1b8f1a73b4ba1b.
    Starting web request.
    Executed: 'ProblemTestHandler.HandleTestQueueMessage' (Succeeded)
    Got response, statuscode=OK.
    Finished web request.
    
    Unhandled Exception: System.ObjectDisposedException: BrokeredMessage has been disposed.
       at Microsoft.ServiceBus.Messaging.BrokeredMessage.ThrowIfDisposed()
       at Microsoft.ServiceBus.Messaging.BrokeredMessage.BeginComplete(AsyncCallback callback, Object state)
       at System.Threading.Tasks.TaskFactory`1.FromAsyncImpl(Func`3 beginMethod, Func`2 endFunction, Action`1 endAction, Object state, TaskCreationOptions creationOptions)
       at Microsoft.ServiceBus.Common.Parallel.TaskHelpers.CreateTask(Func`3 begin, Action`1 end, Object state)
    --- 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.GetResult()
       at Wkb.eInvoicing.Worker.Handlers.ProblemTestHandler.<HandleTestQueueMessage>d__1.MoveNext() in C:\Dev\eInvoicing\src\Wkb.eInvoicing.Worker\Handlers\ProblemTestHandler.cs:line 43
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<>c.<ThrowAsync>b__6_1(Object state)
       at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
       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.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
       at System.Threading.ThreadPoolWorkQueue.Dispatch()
       at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
    

    正如您在输出中看到的,我的JobHost容器认为该方法在执行 httpClient。GetAsync() 方法:

    Starting web request.
    Executed: 'ProblemTestHandler.HandleTestQueueMessage' (Succeeded)
    Got response, statuscode=OK.
    

    当我用非异步替代方案(例如使用RestSharp)替换web请求时,问题不会发生。你知道这个问题的根源是什么吗?

    1 回复  |  直到 7 年前
        1
  •  3
  •   Scott Chamberlain    7 年前

    你几乎不应该使用 async void 除非您正在编写事件处理程序,否则应该使用 async Task 相反,这让系统知道您的webjob尚未完成,因此它不会在完成之前尝试强制关闭资源。