反序列化时出现线程错误 JSON

Threading error while deserializing JSON

所以我为我的客户制作了一个请求包装器,一切正常。但是突然(我不知道为什么)JsonConvert.DeserializeObject<T>(c) 抛出经典异常

The calling thread cannot access this object because a different thread owns it

好吧,除了这个,我没有看到任何其他线程。所有这些都是局部变量,根据 Newtonsoft https://github.com/JamesNK/Newtonsoft.Json/issues/469

A new JsonSerializerInternalReader is created each time you deserialize an object

你知道这个异常所讨论的另一个线程在哪里吗?

    public static Task<Response<T>> _reqWrapper<T>(Func<Task<HttpResponseMessage>> request) 
        where T : class
    {
        return Task.Run(async () =>
        {
            var response = new Response<T>();

            var hrm = await request().ConfigureAwait(false);                              
            var c = await hrm.Content.ReadAsStringAsync().ConfigureAwait(false);
            response.Content = JsonConvert.DeserializeObject<T>(c);

            return response;
        });

已经试过了,但运气不好。

response.Content = await Task.Run(() => JsonConvert.DeserializeObject<T>(c));

更新

为了确保那条线是我投掷的那条线:

T t = null;
try
{
    t = JsonConvert.DeserializeObject<T>(c);
}
catch { }
response.Content = t

一切都很好运行。有什么线索吗?

更新 2

堆栈跟踪

我在这里看到的是序列化程序正在尝试访问主 window。我不得不说这是在 ShowDialog() window 内部发生的,所以我猜主 window 不可用。但我不确定我是否正确或如何解决这个问题。

at System.Windows.Threading.Dispatcher.VerifyAccess() at System.Windows.Application.get_MainWindow() at ControliWindows.Globals.Controli.get_Window() in C:... at ControliWindows.Globals.Framework.Modalizer.SaveableModel1..ctor() in C:... at ControliWindows.Views.Modals.AccountMm..ctor() in C:... at CreateControliWindows.Views.Modals.AccountMm() at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value) at ControliWindows.Globals.Connection.<>c__DisplayClass39_0`1.<<_reqWrapper>b__0>d.MoveNext() in C:...

通过使用 ConfigureAwait(false),您明确告诉 await 在执行 await 后不要尝试在同一线程上继续执行代码。

来自the documentation

continueOnCapturedContext

Type: System.Boolean

true to attempt to marshal the continuation back to the original context captured; otherwise, false.

请尝试使用 ConfigureAwait(true)

at System.Windows.Threading.Dispatcher.VerifyAccess() at System.Windows.Application.get_MainWindow() at ControliWindows.Globals.Controli.get_Window() in C:... at ControliWindows.Globals.Framework.Modalizer.SaveableModel1..ctor() in C:... at ControliWindows.Views.Modals.AccountMm..ctor() in C:... at

这就是你问题的根源。这是正在发生的一系列事件:

  • 你的 TControliWindows.Views.Modals.AccountMm 并且 DeserializeObject 必须制作一个新的
  • AccountMm 的构造函数它正在创建一个 ControliWindows.Globals.Framework.Modalizer.SaveableModel1
  • SaveableModel1 的构造函数正在读取 属性 ControliWindows.Globals.Controli.Window
  • Controli.Window 它正在读取 属性 System.Windows.Application.Window
  • Application.Window 只能从 UI 线程读取,这整个事件链发生在 Threadpool 线程上并导致您的异常。

最简单的解决方案是让 ControliWindows.Globals.Controli.Window 检测它是否不在 UI 线程上,以及是否未调用 UI 以获取 [=20= 的值].

public static class Controli
{
    public Window Window
    {
        get
        {
            var application = Application.Current;
            if(application == null)
                return null;
            try
            {
                return application.MainWindow;
            }
            catch(InvalidOperationException)
            {
                return application.Dispatcher.Invoke(() => application.MainWindow);
            }
        }
    }
}

反序列化发生在另一个线程中。它打开自己的线程