【发布时间】:2018-01-16 07:27:21
【问题描述】:
在 Xamarin 项目中,我有带有以下代码的 PCL 库。
我们定义一个ConcurrentQueue<SyncRequest>。在对象初始化时,消费者Task 已附加:
_syncConsumer = new Task(
ProcessSyncQueue,
_syncConsumerCancellationTokenSource.Token);
_syncConsumer.Start();
ProcessSyncQueue方法扫描同步队列并调用GetSyncableEntity方法:
private async void ProcessSyncQueue()
{
while (true)
{
SyncRequest syncRequest;
if (_syncQueue.TryDequeue(out syncRequest))
{
var syncableEntity = GetSyncableEntity(syncRequest);
}
}
}
GetSyncableEntity 依次执行 Json 反序列化:
private T GetSyncableEntity(SyncRequest syncRequest)
{
T syncableEntity = default(T);
try
{
syncableEntity = JsonConvert.DeserializeObject<T>(syncRequest.SynchronizationContent);
}
catch (Exception e)
{
}
return syncableEntity;
}
在此步骤中,我们收到带有“线程被中止”消息的ThreadAbortedException。
堆栈跟踪:
at Newtonsoft.Json.JsonTextReader.FinishReadStringIntoBuffer(Int32 charPos, Int32 initialPosition, Int32 lastWritePosition)
at Newtonsoft.Json.JsonTextReader.ReadStringIntoBuffer(Char quote)
at Newtonsoft.Json.JsonTextReader.ParseProperty()
at Newtonsoft.Json.JsonTextReader.ParseObject()
at Newtonsoft.Json.JsonTextReader.Read()
at Newtonsoft.Json.JsonReader.ReadAndAssert()
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.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)
谁能帮助我们了解发生了什么以及应该如何反序列化?
更新:
我发布了更多代码,正如审阅者建议的那样,我删除了CancellationTokenSource,使用Task.Run 初始化消费者和await 它。
并创建了一些这样的测试实现:
protected void RequestSynchronizationFor(
string synchronizationKey,
T entity)
{
if (!_isInitialized)
{
InitializeSyncRequestsQueue();
}
_syncQueue.Enqueue(GetSyncRequest(synchronizationKey, entity));
}
所以我们请求实体同步调用RequestSynchronizationFor 方法。如果是冷运行,我们从 db 调用 InitializeSyncRequestsQueue 初始化队列并等待 Task.Run 消费者线程。
private async void InitializeSyncRequestsQueue()
{
var syncRequests = GetSyncedRequests();
foreach (var syncRequest in syncRequests)
{
_syncQueue.Enqueue(syncRequest);
}
await Task.Run(ProcessSyncQueue);
}
消费者任务和以前一样:
private async Task ProcessSyncQueue()
{
while (true)
{
SyncRequest syncRequest;
if (_syncQueue.TryDequeue(out syncRequest))
{
var syncableEntity = GetSyncableEntity(syncRequest);
}
}
}
仍然有同样的异常。不确定这是否明智,但我正在运行单元测试中的代码。有什么建议吗?
更新2:
在我在第一个“更新”中发布的更改后,调用堆栈也发生了一些变化:
at Newtonsoft.Json.JsonSerializer.get_MetadataPropertyHandling()
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.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)
更新 3: 我提取了假服务中的所有代码,但仍然有相同的异常,同时尝试反序列化:
public class JsonDeserializeService<T>
{
private readonly bool _isInitialized;
private readonly ConcurrentQueue<SyncRequest> _syncQueue;
public JsonDeserializeService()
{
_isInitialized = false;
_syncQueue = new ConcurrentQueue<SyncRequest>();
}
public void RequestSynchronizationFor(
string synchronizationKey,
T entity)
{
if (!_isInitialized)
{
InitializeSyncRequestsQueue();
}
_syncQueue.Enqueue(GetSyncRequest(synchronizationKey, entity));
}
private async void InitializeSyncRequestsQueue()
{
var syncRequests = Enumerable.Empty<SyncRequest>();
foreach (var syncRequest in syncRequests)
{
_syncQueue.Enqueue(syncRequest);
}
await Task.Run(ProcessSyncQueue);
}
private async Task ProcessSyncQueue()
{
while (true)
{
SyncRequest syncRequest;
if (_syncQueue.TryDequeue(out syncRequest))
{
var syncableEntity = GetSyncableEntity(syncRequest);
}
}
}
private T GetSyncableEntity(SyncRequest syncRequest)
{
T syncableEntity = default(T);
try
{
syncableEntity = JsonConvert.DeserializeObject<T>(syncRequest.SynchronizationContent);
}
catch (Exception e)
{
}
return syncableEntity;
}
private SyncRequest GetSyncRequest(string synchronizationKey, T entity)
{
return new SyncRequest()
{
SynchronizationContent = JsonConvert.SerializeObject(entity),
SynchronizationDelayUntil = DateTime.Now
};
}
}
从单元测试触发:
public void Syncable_Service_Should_Not_Generate_Exception()
{
var syncService = new JsonDeserializeService<FakeSyncableEntity>();
syncService.RequestSynchronizationFor("syncKey", new FakeSyncableEntity() { Content = "Content" });
}
【问题讨论】:
-
我认为您应该链接更多代码并尝试隔离问题。从您所展示的内容来看,很难判断什么可能会中止线程。关注 _syncConsumerCancellationTokenSource.Token 将是我认为的罪犯
-
这在 ConcurrentQueue 之外是否有效?
-
你不应该使用“新任务”——使用 Task.Run(ProcessSyncQueue, _syncConsumerCancellationTokenSource.Token) 代替。还有你的 _syncConsumer 对象会发生什么?你在等待吗?错误消息可能暗示任务对象在其仍在运行时被释放,并且其关联的线程被中止。
-
@Dbl 我更新了我的问题
-
@ckuri 按照你的建议做了,还是一样
标签: c# json xamarin json.net task