Mail über SMTP im Thread geht nicht?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Mail über SMTP im Thread geht nicht?

    Hallo,

    ich nutze das Framework SMPSMTPMessage, um vom iPhone Mail über SMTP zu verschicken.
    Das klappt auch alles sehr gut, aber wenn größere Dateien im Anhang sind, fängt die App an zu ruckeln und der Aufruf einer URL wird geblockt, bis die Mail weg ist.

    Also dachte ich, das Versenden in einen Thread zu packen und im Hintergrund laufen zu lassen.
    Das mache ich so:

    Quellcode

    1. [NSThread detachNewThreadSelector:@selector(doStartRunningActionThread) toTarget:self withObject:nil];


    Der eigentliche Aufruf ist hier:

    Quellcode

    1. -(void)doStartRunningActionThread {
    2. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    3. int id = [self getNextID];
    4. CommTool *cTool = [[CommTool alloc] initWithDelegate:self];
    5. runningActionThread = [cTool startMailForID:id forDelegate:self];
    6. [pool drain];
    7. }


    Dann geht aber keine Mail mehr raus ;(
    Ich sehe im Debugger, dass alles schön vorbereitet wird und komme bis ins das Framework hinein. In der Klasse SKPSMTPMessage.m wird in der Funkction -(BOOL)send ein Timer gesetzt, um das Timeout zu checken und außerdem werden ein NSInputStream und ein NSOutputstream geöffnet:

    Quellcode

    1. self.connectTimer = [NSTimer scheduledTimerWithTimeInterval:connectTimeout
    2. target:self
    3. selector:@selector(connectionConnectedCheck:)
    4. userInfo:nil
    5. repeats:NO];
    6. [NSStream getStreamsToHostNamed:relayHost port:relayPort inputStream:&inputStream outputStream:&outputStream];
    7. if ((inputStream != nil) && (outputStream != nil))
    8. {
    9. sendState = kSKPSMTPConnecting;
    10. isSecure = NO;
    11. [inputStream retain];
    12. [outputStream retain];
    13. [inputStream setDelegate:self];
    14. [outputStream setDelegate:self];
    15. [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
    16. forMode:NSRunLoopCommonModes];
    17. [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
    18. forMode:NSRunLoopCommonModes];
    19. [inputStream open];
    20. [outputStream open];
    21. self.inputString = [NSMutableString string];
    22. return YES;
    23. }
    24. else
    25. {
    26. [self.connectTimer invalidate];
    27. self.connectTimer = nil;
    28. [delegate messageFailed:self
    29. error:[NSError errorWithDomain:@"SKPSMTPMessageError"
    30. code:kSKPSMTPErrorConnectionFailed
    31. userInfo:[NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Unable to connect to the server.", @"server connection fail error description"),NSLocalizedDescriptionKey,
    32. NSLocalizedString(@"Try sending your message again later.", @"server generic error recovery"),NSLocalizedRecoverySuggestionErrorKey,nil]]];
    33. return NO;
    34. }
    Alles anzeigen


    Weder der Timer noch der Eventhandler der Streams werden jedoch aufgerufen und so bleibt die Mail auf der Strecke.

    Wenn ich den Vorgang nicht als Thread, sondern direkt aufrufe, läuft alles wie gewünscht!

    Kollidieren hier Thread und der RunLoop? Kann man das überhaupt so koppeln??
  • Es macht mich stuzig, dass du sowohl beim Alloc/Init des CommTool ein Delegate angiebst als auch beim Methodenaufruf für den Start der MAilverschickung. Das ist ja nicht normal oder?

    Weiterhin würde ich auch hier auf die neue Blockmehtode setzen.

    XML Frage

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • Thallius schrieb:

    Es macht mich stuzig, dass du sowohl beim Alloc/Init des CommTool ein Delegate angiebst als auch beim Methodenaufruf für den Start der MAilverschickung. Das ist ja nicht normal oder?
    Es geht dabei um 2 verschiedene Protokolle. Hat aber mit dem Problem definitiv nichts zu tun.

    Thallius schrieb:

    Weiterhin würde ich auch hier auf die neue Blockmehtode setzen.
    Aber die hilft doch nur, einen asynchronen Request abzusetzen, oder verstehe ich das falsch?
    Ich will doch das Mailing im Hintergrund laufen lassen und nicht den erwähnten Aufruf der URL.
    Dieser Request ist an eine Aktion des Anwenders gekoppelt und muss unbedingt zeitnah abgearbeitet werden, weil mit der Antwort vom Server der nächste Dialog erstellt wird.
  • 1. Dokumentaiton zu NSRunLoop

    2.

    Quellcode

    1. [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
    2. forMode:NSRunLoopCommonModes];
    3. [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
    4. forMode:NSRunLoopCommonModes];
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Amin Negm-Awad schrieb:

    1. Dokumentaiton zu NSRunLoop
    Funktioniert! Danke!!
    Ich habe es erst einmal mit

    Quellcode

    1. [[NSRunLoop currentRunLoop] run];
    ausprobiert, um zu sehen, ob überhaupt was geht und es läuft richtig gut ^^
    Beim weiteren Lesen komme ich aber ins Grübeln: kann ich run benutzen oder nehme ich besser runMode:beforeDate:?

    Amin Negm-Awad schrieb:

    2.

    Quellcode


    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSRunLoopCommonModes];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSRunLoopCommonModes];
    Diesen Hinweis verstehe ich ich nicht...
    Warum startet der Runloop ohne mein Zutun beim normalen Aufruf und im Thread nicht?
  • Gibbsnich schrieb:

    Amin Negm-Awad schrieb:

    1. Dokumentaiton zu NSRunLoop
    Funktioniert! Danke!!
    Ich habe es erst einmal mit

    Quellcode

    1. [[NSRunLoop currentRunLoop] run];
    ausprobiert, um zu sehen, ob überhaupt was geht und es läuft richtig gut ^^
    Beim weiteren Lesen komme ich aber ins Grübeln: kann ich run benutzen oder nehme ich besser runMode:beforeDate:?

    -run startet sie unendlich. Das willst du im Zweifel nicht. Wenn du ein Time-Out imlementieren willst, wird es wohl nur mit -runMode:beforeDate: gehen.

    Gibbsnich schrieb:


    Amin Negm-Awad schrieb:

    2.

    Quellcode


    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSRunLoopCommonModes];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSRunLoopCommonModes];
    Diesen Hinweis verstehe ich ich nicht...
    Warum startet der Runloop ohne mein Zutun beim normalen Aufruf und im Thread nicht?

    Ah, hatte mich verlesen.

    Im Main-Thread startet sie "automatisch" (sie wird schon gestartet, nur macht das Cocoa selbst), wenn es sich um eine Applikation handelt. (Versuche es mal i einem Foundation-Tool. Dort wird du dasselbe Problem haben.) Da sollen ja Nutzerevents empfangen werden. In weiteren Threads ist es völlig unbestimmt, ob da eine Runloop benötigt wird, letztlich, also, ob der Kontrollfluss ereignisgetrieben ist.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Amin Negm-Awad ()