c# - Json.Net 中的 "Current error context error is different to requested error"异常

标签 c# multithreading json.net nest elasticsearch-net

上下文

我用 C# 编写了一个并行作业框架,用于从 ElasticSearch 集群导入/导出大量数据。为此,我将单个项目的每次导入或导出建模为一个对象,该对象在某个时刻由框架执行。为了与 ElasticSearch 交互,我使用了 NEST(官方 .NET ElasticSearch 客户端库)v1.7.1 和 JSON.Net 7.0.1。

每个导入/导出任务对象都使用 NEST 与 ElasticSearch 交互。出于性能原因,我编写了一个代理类,它将任务对象生成的搜索请求分组为固定大小的批处理,以与 NEST 的 _msearch API 一起使用。此类的调用者被延迟,直到其批处理返回。 That class is available here .

我的框架将每个导入/导出任务的结果包装为“bool”或“Exception”。即使遇到个别项目的错误,整个过程也能够继续。

问题

在几个小时的任务无错误完成后,我看到以下异常引发了数千次:

System.InvalidOperationException: Current error context error is different to requested error.
    at _____.Matcher.<GetBestMatchAsync>d__15.MoveNext() in C:\\_work\\edc7a363\\_____\\Matcher.cs:line 266
    --- 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`1.GetResult()
    _____.MatchBlock`1.<ExecuteAsyncInternal>d__19.MoveNext() in C:\\_work\\edc7a363\\_____\\MatchBlock.cs:line 111
    --- 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.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
    at _____.Block.BlockBase.<ExecuteAsync>d__11.MoveNext() in C:\\_work\\edc7a363\\_____\\Block\\BlockBase.cs:line 33

这是抛出异常的代码(来自上面链接的批量搜索器类):

try
{
    var bulkResponse = Client.MultiSearch(searchDescriptor);
    var items = bulkResponse.GetResponses<T>().ToList();

    // Set response values and release all waiting tasks
    var zip = currentBuffer.Zip(items, (op, result) => new { op, result });
    foreach (var a in zip)
    {
        a.op.Response = a.result;
        a.op.Cts.Cancel();
    }
}
catch (Exception e)
{
    foreach (var op in currentBuffer)
    {
        op.Error = e;
        op.Cts.Cancel();
    }
}

其中 Client 是一个 IElasticClient

谷歌搜索异常消息将我带到 this method in the JsonSerializerInternalBase class in JSON.Net ,似乎在每次反序列化后执行:

private ErrorContext GetErrorContext(object currentObject, object member, string path, Exception error)
{
    if (_currentErrorContext == null)
    {
        _currentErrorContext = new ErrorContext(currentObject, member, path, error);
    }

    if (_currentErrorContext.Error != error)
    {
        throw new InvalidOperationException("Current error context error is different to requested error.");
    }

    return _currentErrorContext;
}

假设单个 NEST 对象被跨多个线程的每个操作重用——我认为 NEST 只使用一个 JsonSerializer 实例——这让我认为 JSON.Net 的这一部分不是线程安全的。尽管奇怪的是错误直到运行几个小时后才开始发生。

如何进一步调试?

最佳答案

我的同事最终追查到错误 - 这是由于从另一个 JsonConverter 调用的 JsonConverter 内部抛出的异常。 “错误上下文”是一个内部 JSON.Net 事物,用于跟踪最后抛出的异常。似乎异常是由错误的 JsonConverter 处理的。我们向内部 JsonConverter 添加了一个标志,让它知道在特定上下文中不要抛出异常。

关于c# - Json.Net 中的 "Current error context error is different to requested error"异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34396039/

相关文章:

c# - 如何在 IE9 中使用 MSHTML 的 addEventListener 添加事件监听器?

c# - 异步添加内容(线程+ajax)

c# - 在返回给客户端之前修改 JSON 的通用方法

c# - 使用 Json.NET lib 通过 json 发送 javascript 函数

c# - Entity Framework - 使用默认参数调用存储过程

c# - 垃圾收集 - 一个有效但另一个无效,怎么会这样?

c# - 如何在 C# 中返回空 XML(类型 XmlElement)?

python - 在Python中,我需要保护多线程进程之间的数据传输吗?

c# - MongoDb Upsert死锁

asp.net-web-api - 在 ASP.NET Web API 中反序列化为派生类