所以我为我的客户端做了一个请求包装器,一切都很好。但是突然(我不知道为什么)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:…
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.AccountMm
和DeserializeObject
必须使一个新的 -
AccountMm
的构造函数正在创建ControliWindows.Globals.Framework.Modalizer.SaveableModel1
- 在
Controli.Window
中,它正在读取System.Windows.Application.Window
属性 -
Application.Window
只能从UI线程读取,这整个事件链发生在线程池线程上并导致你的异常。
SaveableModel1
的构造函数正在读取属性ControliWindows.Globals.Controli.Window
最简单的解决方案是让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)
代替
反序列化发生在另一个线程中。它打开自己的线程