taskcanceledexception一个任务被取消

时间:2018-07-26 16:26:48

标签: c# exception logging httpclient sentry

我收到错误 taskcanceledexception一个任务被取消,没有任何内部异常详细信息,我在Sentry中未收到任务取消的异常。如何查看此异常的堆栈跟踪是什么或需要对代码进行哪些更改?

谢谢

    private T CallDiffbotAndDeserialise<T>(string baseUrl, string pageUrl, int maxTags, int minimumTagConfidencePercentage)
    {
        var client = diffBotConnection.GetClient();

        client.BaseAddress = new Uri(baseUrl);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        try
        {
            HttpResponseMessage response = client.GetAsync($"?token={settings.DiffBotToken}&maxTags={maxTags}&tagConfidence={minimumTagConfidencePercentage / 100}&url={Uri.EscapeDataString(pageUrl)}&ts={DateTime.Now.ToSafeCacheString()}").Result;
            string responseString = response.Content.ReadAsStringAsync().Result;
            T diffBotResponse = JsonConvert.DeserializeObject<T>(responseString);

            return diffBotResponse;
        }
        catch (AggregateException e) // If the task is cancelled or times out
        {
            return default(T);
        };
    }

API连接:

public abstract class APIConnection : IDisposable
{
    protected HttpClient Client;
    private bool disposed = false;

    protected APIConnection() : this(3000) { }

    protected APIConnection(int timeOut)
    {
        Client = new HttpClient()
        {
            Timeout = TimeSpan.FromMilliseconds(timeOut)
        };
    }

    public HttpClient GetClient() => Client;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                Client.Dispose();
            }
            disposed = true;
        }
    }

1 个答案:

答案 0 :(得分:0)

您正在呼叫.Result,它总是抛出AggregateException

这意味着您不仅会捕获TaskCancelledExceptionOperationCancelledException,还将捕获两次调用.Result所抛出的任何异常。

因为您正在处理异常并隐藏了发生过的事实(通过捕获和返回),Sentry不会知道它。如果要将事件发送给Sentry,则需要手动调用Sentry客户端。

使用SharpRaven

var ravenClient = new RavenClient("dsn"); // Initialize the client
ravenClient.CaptureEvent(new SentryEvent(exception));

使用new SDK Sentry is developing(仍是预览版):

// Initialize the SDK only once, at the start of the app
using (SentrySdk.Init("dsn"))  
{
    SentrySdk.AddBreadcrumb($"Starting a web request to: {baseUrl}");
    try
    {
       // make request
    }
    catch (Exception e)
    {
        SentrySdk.CaptureException(exception);
    }
}

在此示例中,我添加了一个breadcrumb,如果发生事件(例如,捕获上述类似的异常),该事件将与事件一起发送。

还请注意,新的SDK会自动检测未处理的异常。这不是您的示例的情况,因为您正在明确捕获它。

我认为必须提及的一点是,理想情况下,应避免通过调用.Result阻塞线程,而应使用async/await

await关键字将Exception从出现故障的Task中解包。 这意味着您的catch块现在可以捕获OperationCancelledException了。其他任何错误(例如完全无法连接到服务器)都不会进入您的catch块,而是会使堆栈冒泡。