2017-08-08 24 views
3

在Xamarin项目中,我有PCL库,下面的代码。JsonConvert.DeserializeObject和ThreadAbortedException

我们定义了一个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方法。如果是冷运行,我们从数据库初始化队列,调用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); 
      } 
     } 
    } 

还是得到了同样的异常。不知道它是否合理,但我正在运行单元测试中的代码。有什么建议么?

UPDATE2:

我做了改动后我张贴在第一个“UPDATE”,调用栈被改变了一点,以及:

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" }); 
    } 
+1

我想你应该链接更多的代码,并尝试隔离问题。从你所展示的内容来看,很难说出可能会中止的主题。在_syncConsumerCancellationTokenSource之后。令牌将是我认为的罪犯 – Dbl

+0

这是否在ConcurrentQueue之外工作? –

+1

你不应该使用“新的任务” - 而是使用Task.Run(ProcessSyncQueue,_syncConsumerCancellationTokenSource.Token)。你的_syncConsumer对象又会发生什么?你在等待吗?错误消息可能暗示当它仍在运行并且其相关联的线程被中止时正在处理的任务对象。 – ckuri

回答

0

此行为的原因非常简单。 您的测试比异步任务更结束。当测试结束时,它会为子线程引发ThreadAbortException。

您需要调用task.Wait()使主线程等待任务完成。

相关问题