反序列化时出现线程错误 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 后不要尝试在同一线程上继续执行代码。
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
这就是你问题的根源。这是正在发生的一系列事件:
- 你的
T
是 ControliWindows.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);
}
}
}
}
反序列化发生在另一个线程中。它打开自己的线程
所以我为我的客户制作了一个请求包装器,一切正常。但是突然(我不知道为什么)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 后不要尝试在同一线程上继续执行代码。
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
这就是你问题的根源。这是正在发生的一系列事件:
- 你的
T
是ControliWindows.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);
}
}
}
}
反序列化发生在另一个线程中。它打开自己的线程