Xamarinプロジェクトでは、次のコードを持つPCLライブラリがあります。JsonConvert.DeserializeObjectとThreadAbortedException
ConcurrentQueue<SyncRequest>
を定義します。
_syncConsumer = new Task(
ProcessSyncQueue,
_syncConsumerCancellationTokenSource.Token);
_syncConsumer.Start();
をProcessSyncQueue
方法は、同期キューを走査しGetSyncableEntity
メソッド呼び出し:オブジェクトの初期化に消費者Task
が装着された順番に
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)
は誰が起こっていると、それがどのように直列化復元されなければならないかを理解するために私たちを助けることができますか?
UPDATE: 私は消費者とawait
それを初期化するためにTask.Run
を使用して、レビューアが、私はCancellationTokenSource
を削除した提案として、もう少しコードを投稿してください。 そして、このようないくつかのテスト実装を作成しました:だから私たちはRequestSynchronizationFor
メソッドを呼び出して同期させることを企業に要求し
protected void RequestSynchronizationFor(
string synchronizationKey,
T entity)
{
if (!_isInitialized)
{
InitializeSyncRequestsQueue();
}
_syncQueue.Enqueue(GetSyncRequest(synchronizationKey, entity));
}
。コールドランであれば、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)
UPDATE 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に続いています。トークンは私が考える犯人になるでしょう – Dbl
これはConcurrentQueueの外部で動作しますか? –
「新しいタスク」を使用しないでください。代わりにTask.Run(ProcessSyncQueue、_syncConsumerCancellationTokenSource.Token)を使用してください。 _syncConsumerオブジェクトはどうなりますか?あなたはそれを待っていますか?エラーメッセージは、実行中のタスクオブジェクトと関連するスレッドが中止されたときに、そのタスクオブジェクトが処理されることを示唆することがあります。 – ckuri