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

本文关键字:线程 错误 JSON 反序列化 | 更新日期: 2023-09-27 18:17:17

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

调用线程不能访问这个对象,因为它被另一个线程拥有

嗯,我没有看到任何其他线程,但这一个。它们都是局部变量,根据Newtonsoft https://github.com/JamesNK/Newtonsoft.Json/issues/469

每次反序列化对象时都会创建一个新的JsonSerializerInternalReader

你有任何线索在哪里这个异常是谈论另一个线程?

    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

堆栈跟踪

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

在System.Windows.Threading.Dispatcher.VerifyAccess ()在System.Windows.Application.get_MainWindow ()control . get_window () in C:…在C:…在C:…在CreateControliWindows.Views.Modals.AccountMm ()在Newtonsoft.Json.Serialization.JsonSerializerInternalReader。创建新对象(JsonReader reader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty,字符串id,布尔值& &;createdFromNonDefaultCreator)在Newtonsoft.Json.Serialization.JsonSerializerInternalReader。创建对象(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)在Newtonsoft.Json.Serialization.JsonSerializerInternalReader。create evalueinternal (JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)在Newtonsoft.Json.Serialization.JsonSerializerInternalReader。反序列化(JsonReader阅读器,类型objectType,布尔checkAdditionalContent)在Newtonsoft.Json.JsonSerializer。DeserializeInternal(JsonReader阅读器,类型objectType)在Newtonsoft.Json.JsonSerializer。反序列化(JsonReader reader,类型objectType)在Newtonsoft.Json.JsonConvert。DeserializeObject(字符串值,类型类型,JsonSerializerSettings设置)在Newtonsoft.Json.JsonConvert。DeserializeObject[T](字符串值,JsonSerializerSettings设置)在Newtonsoft.Json.JsonConvert。DeserializeObject [T](字符串值)在controlliwindows . global . connection .<>c__DisplayClass39_0 ' 1.<<_reqWrapper>b__0> d.m emovenext () in C:…

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

at System.Windows.Threading.Dispatcher.VerifyAccess() at System.Windows.Application.get_MainWindow() at ControliWindows.Globals.Controli.get_Window() in C:…在C:…在C:…在

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

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

最简单的解决方案是让ControliWindows.Globals.Controli.Window检测它是否不在UI线程上,如果它没有调用到UI以获得Application.Window的值。

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);
            }
        }
    }
}

通过使用ConfigureAwait(false),您显式地告诉您的await在执行await后不要尝试在同一线程上恢复执行代码。

来自文档:

continueOnCapturedContext

类型:系统。布尔

true尝试将延续封送回捕获的原始上下文;否则,

试试用ConfigureAwait(true)代替

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