2010-12-09 24 views
2

Je fais de la programmation asynchrone, et mon code fonctionne, la plupart du temps, mais parfois non. L'essentiel est: je crée une paire de socket, crée des flux de lecture et d'écriture, puis quand je veux écrire quelque chose, je le programme sur une boucle d'exécution d'un thread séparé. Comme si:CFWriteStreamScheduleWithRunLoop fonctionne parfois, parfois non?

CFStreamClientContext context = {0, sc, NULL, NULL, NULL}; 
if (CFWriteStreamSetClient(sc.writeStream, kCFStreamEventCanAcceptBytes | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, myWriteStreamCallBack, &context)) { 
CFWriteStreamScheduleWithRunLoop(sc.writeStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); 
} 

... où myWriteStreamCallback est une fonction statique de la forme correcte ...

les prises/courants ont été ouverts comme ceci:

CFReadStreamRef readStream = NULL; 
CFWriteStreamRef writeStream = NULL; 

@try { 
    // create a pair of streams to the host and open them 

    CFStreamCreatePairWithSocketToCFHost(kCFAllocatorDefault, scomm.host, SERVER_PORT, &readStream, &writeStream); 
    if (readStream == NULL)  @throw [[[CommunicationReadStreamNotCreatedException alloc] init] autorelease]; 
    if (writeStream == NULL) @throw [[[CommunicationWriteStreamNotCreatedException alloc] init] autorelease]; 
    if (!CFReadStreamOpen(readStream)) @throw [[[CommunicationReadStreamNotOpenedException alloc] init] autorelease]; 
    if (!CFWriteStreamOpen(writeStream)) @throw [[[CommunicationWriteStreamNotOpenedException alloc] init] autorelease]; 
    ... 

maintenant au problème : ce code (et il y en a plus, si ça peut aider quelqu'un), est correct pour la plupart, parce que ça marche surtout. Cependant, parfois, au tout début du programme, je peux essayer d'envoyer des données de cette façon, et le rappel pour le socket sera correctement placé sur la boucle d'exécution, mais il ne sera jamais appelé. Plus tard dans le programme, le même code sera exécuté avec un autre socket, et le callback sera appelé (les sockets vont à la même adresse).

Je sais que c'est vague, mais avant que je commence à publier tout le code, est-ce que quelqu'un a des idées approximatives sur les choses qui pourraient potentiellement causer cela? Les rappels parfois ne sont pas appelés sur runloops, c'est. Oh oui, je dois ajouter qu'il s'agit évidemment d'un type de condition de concurrence - je peux difficilement faire disparaître le problème en ajoutant des instructions de journalisation aux bons endroits. Et puis, ça marche parfois et parfois non, avec exactement le même code. Fun amusant.

Répondre

1

J'ai obtenu une solution de « quinn le eskimo » sur les forums de pomme:

Le problème est la résolution de l'hôte fait dans un fil et le CFHostRef utilisé dans d'autres threads. C'est mauvais.

CFHost création effectuée dans le même thread (l'objet scomm.host, ci-dessus) résout le problème.