Initialement:
Scénario:
Code:
[DataContract(IsReference=true)]
public class Message
{
[DataMember]
public string TopicName { get; set; }
[DataMember]
public string EventData { get; set; }
[DataMember]
public SerializableDictionary<string, FuturesLineAsset> FuturesLineDictionary { get; set ; }
}
Pensées:
Parent:
public class FuturesAsset
{
public string AssetName { get; set; }
public BindableDictionary<string, FuturesLineAsset> AssetLines { get; private set; }
public FuturesAsset()
{
AssetLines = new BindableDictionary<string, FuturesLineAsset>();
}
public FuturesAsset(string assetName)
{
AssetLines = new BindableDictionary<string, FuturesLineAsset>();
AssetName = assetName;
}
}
Enfant:
public class FuturesLineAsset
{
public string ReferenceAsset { get; set; }
public string MID { get; set; }
public double LivePrice { get; set; }
public DateTime UpdateTime { get; set; }
public DateTime LastContributedTime { get; set; }
public double Spread { get; set; }
public double Correlation { get; set; }
public DateTime Maturity { get; set; }
public double ReferenceCurve { get; set; }
public FuturesLineAsset(string mID, string referenceAsset, double livePrice)
{
MID = mID;
ReferenceAsset = referenceAsset;
ReutersLivePrice = livePrice;
}
}
cette exception n'est pas liée à la référence circulaire, elle consiste simplement en un dépassement de délai lorsque vous essayez de transférer des tonnes de données sur le réseau.
Les valeurs par défaut fournies avec WCF sont très faibles (elles ont été modifiées dans WCF 4, je crois). Lisez ces deux articles sur le blog, ils devraient vous donner une idée de la façon de détrôner votre service:
Création de services WCF hautes performances
Update: il existe également un certain nombre de délais d'attente différents dans la configuration de WCF et selon que vous parliez du client ou du serveur dont vous parlez, vous devez mettre à jour une clause de délai d'attente différente ... lisez ceci thread sur ce que chacun signifie et vous devriez être capable de trouver celui que vous avez besoin de croiser. Ou, vous pouvez simplement définir chaque délai d'attente sur int.max si vous ne vous souciez pas vraiment de savoir si un appel peut prendre un peu de temps.
Cette erreur peut être causée par un certain nombre de choses. Bien qu’il s’agisse d’un problème de minutage dans ce cas, cela n’a généralement rien à voir avec les minutages, surtout si l’erreur est reçue immédiatement . Les raisons possibles sont:
Ce problème est dû à un long processus d'initialisation appelé à partir de l'événement OnStart d'un programme d'installation de l'hôte de service Windows. Fixé en définissant le mode de sécurité et les délais d'attente pour la liaison TCP.
// Create a channel factory.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.Transport;
b.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
b.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;
b.MaxReceivedMessageSize = 1000000;
b.OpenTimeout = TimeSpan.FromMinutes(2);
b.SendTimeout = TimeSpan.FromMinutes(2);
b.ReceiveTimeout = TimeSpan.FromMinutes(10);
Ce problème peut également être dû au fait de ne pas nettoyer le client WCF lorsque vous avez fini de l’utiliser. Dans notre système, nous utilisons le modèle à usage unique en incorporant tous les appels de fonction dans le système pour permettre un nettoyage et une journalisation appropriés. Nous utilisons une version de la classe suivante:
public class WcfWrapper : IDisposable
{
private readonly OperationContextScope _operationContextScope;
private readonly IClientChannel _clientChannel;
public WcfWrapper(IClientChannel clientChannel)
{
_clientChannel = clientChannel;
_operationContextScope = new OperationContextScope(_clientChannel);
}
public void Dispose()
{
_operationContextScope.Dispose();
}
public T Function<T>(Func<T> func)
{
try
{
var result = func();
_clientChannel.Close();
return result;
}
catch (Exception ex)
{
KTrace.Error(ex);
_clientChannel.Abort();
throw;
}
}
public void Procedure(Action action)
{
try
{
action();
_clientChannel.Close();
}
catch (Exception ex)
{
KTrace.Error(ex);
_clientChannel.Abort();
throw;
}
}
}
}
Chaque appel WCF que nous passons dans notre service passe par une classe d'interface définie comme celle-ci:
public sealed class WcfLoginManager : ILoginManager
{
private static LoginManagerClient GetWcfClient()
{
return
new LoginManagerClient(
WcfBindingHelper.GetBinding(),
WcfBindingHelper.GetEndpointAddress(ServiceUrls.LoginManagerUri));
}
public LoginResponse Login(LoginRequest request)
{
using(var loginManagerClient = GetWcfClient())
using (var slice = new WcfWrapper(loginManagerClient.InnerChannel))
{
DSTicket ticket;
DSAccount account;
return slice.Function(() => new LoginResponse(loginManagerClient.Login(request.accountName, request.credentials, out ticket, out account), ticket, account));
}
}
}
En utilisant ce modèle, tous les appels WCF dans le système sont encapsulés avec la méthode Function ou la méthode Procedure, ce qui leur permet de s’assurer d’abord de la consignation de toutes les erreurs et ensuite de s’assurer que le canal est fermé si aucune erreur ne se produit mais annulé si une exception se produit . Enfin, comme dans une déclaration using, la disposition finale du canal est appelée. De cette manière, les erreurs dues à des canaux non nettoyés, ressemblant à cette erreur, seront évitées.
Cette exception s'est produite pour moi lorsque je renvoyais un objet contenant des collections IEnumerable, et une exception s'est produite lors de l'extraction de l'un des membres de la collection. À ce stade, il est trop tard pour le récupérer dans votre code et WCF est supposé conçu pour déconnecter le socket dans ce cas, car il est également trop tardif pour signaler une exception au client, car les résultats de la diffusion en continu ont déjà commencé.
L'erreur WCF:
La connexion de socket a été interrompue. Cela pourrait être dû à une erreur traitement de votre message ou dépassement du délai de réception par le hôte distant ou un problème de ressource réseau sous-jacent. Prise locale le timeout était ...
où les délais signalés sont très proches de 1 minute (par exemple 00:00:59.9680000
) ou 1 minute exactement (c'est-à-dire 00:01:00
) peuvent être causés par un message trop volumineux et un dépassant les paramètres de la liaison .
Cela peut être corrigé en augmentant les valeurs dans le fichier de configuration, par exemple:
<binding name="MyWcfBinding"
maxReceivedMessageSize="10000000"
maxBufferSize="10000000"
maxBufferPoolSize="10000000" />
(à titre d’exemple, vous voudrez peut-être les ajuster).