2012-06-04 13 views
6

Estoy tratando de usar AmazonS3Client para putObject. Lo extraño es que parece funcionar cuando ejecuto mi código putObject en el hilo principal de iOS.AmazonS3Client putObject solo funciona en el hilo principal de iOS?

El código es básicamente lo siguiente:

-(void)uploadVideoToS3 
{ 
    S3PutObjectRequest * videoPOR = [[S3PutObjectRequest alloc] initWithKey:video.onlineVideoID inBucket:video.onlineVideoBucketName]; 
    videoPOR.contentType = @"video/quicktime"; 
    videoPOR.data  = [NSData dataWithContentsOfURL:video.convertedVideoLocalURL]; 
    videoPOR.delegate = self; 

    // Put the thumbnail and video into the specified s3 
    AmazonS3Client * s3 = [AmazonClientManager s3]; 

    [s3 putObject:videoPOR]; 
    [videoPOR release]; 
} 

existe el cubo, tengo permisos, etc. Si simplemente me llamo

[self uploadVideoToS3] 

en mi código (que es el hilo principal) , se ejecuta todo el método de carga de video (tengo algunos NSLogs para probar esto), pero nunca recibo ninguna devolución de llamada de estado, no se lanzan excepciones, y el objeto nunca se pone en su cubo en S3.

Cuando llamo a la función de carga en el hilo principal de este modo:

dispatch_async(dispatch_get_main_queue(), ^(void) { 
        [self uploadVideoToS3]; 
       }); 

consigo devoluciones de llamada progreso, todo funciona, y el objeto se coloca correctamente en el contenedor de S3.

¿Alguien sabe si putObject solo funciona en el hilo principal de iOS? Si es así, sería desafortunado ya que normalmente es el hilo de la interfaz de usuario.

Gracias, Kevin

P. S. He intentado enviar la llamada de función a un hilo no principal con el mismo resultado fallido.

+0

¿con qué código intentaron enviarlo a otro hilo? – Pochi

+0

'dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{[self uploadVideoToS3]});' – kevlar

+0

encontró un artículo interesante en el sitio web de AWS. Usar dispatch_async podría ser el problema. No estoy seguro, pero aquí tienes -> Evita usar dispatch_sync en el hilo principal tanto como sea posible .http: //mobile.awsblog.com/post/Tx1ZZHQHSD0O3SF/Using-the-AWS-SDK-for-iOS-Asynchronously- Parte-IV-Grand-Central-Dispatch-GCD-Best –

Respuesta

4

Estoy pensando que su hilo termina una vez que termina de enviar la solicitud, por lo tanto, las devoluciones de llamada no tienen ningún hilo al que ir. Crear un hilo no significa automáticamente que solo viva para siempre. Una vez que finaliza su tarea, finaliza y se recupera para el grupo de subprocesos. Para hacer esto en otro hilo, vas a tener que diseñar un método que se integre con un ciclo de ejecución. Hay una sección en el Threading Programming Guide en los documentos de Apple.

+0

Ese es un buen punto. Intenté solucionarlo haciendo 'dispatch_queue_create' y luego' dispatch_release' después de que se realiza la carga, pero la carga nunca continúa después de que se crea la cola. Parece que esto sigue siendo víctima de tu teoría? Voy a intentar algunos otros enfoques para extender la vida útil del hilo a través de un ciclo de ejecución, gracias. – kevlar

+1

Las colas están separadas de los hilos. Las colas generarán cualquier cantidad de subprocesos, dependiendo de las condiciones del sistema, para lograr el bloque en el que están trabajando actualmente. – borrrden

+0

Veo, entonces necesito persistir un hilo (NSThread) en lugar de usar decir, NSOperationQueue? – kevlar

2

El problema es que S3PutObjectRequest se ejecuta de forma asíncrona si configura el delegado. El delegado envía sus devoluciones de llamada en el bucle de ejecución actual, que funciona bien en el hilo principal, pero no en un hilo de cola de despacho. Tienes que iniciar tu propio ciclo de ejecución para procesar a los delegados. Todavía estoy tratando de decidir la mejor manera de gestionar esto.

Por supuesto, desearía que simplemente proporcionaran métodos síncronos y asíncronos en lugar de cambiar mágicamente, pero esto se explica en el archivo de encabezado AmazonServiceRequest.h en la propiedad de delegado.

+0

Gracias, me di cuenta de esto manteniendo vivo el hilo con un ciclo de ejecución hasta que termine la carga. – kevlar

2

El método putObject de AmazonS3Client bloquea el hilo principal. Incluso yo estaba enfrentando el problema. Pero encontré una mejor solución en S3TransferManager.

Código Ejemplo:

AmazonS3Client * s3 = [AmazonClientManager s3]; 

S3PutObjectRequest * videoPOR = [[S3PutObjectRequest alloc] initWithKey:video.onlineVideoID inBucket:video.onlineVideoBucketName];     
videoPOR.contentType = @"video/quicktime"; 
videoPOR.data = [NSData dataWithContentsOfURL:video.convertedVideoLocalURL]; 

S3TransferManager *manager = [S3TransferManager new]; 
manager.s3 = s3; 
[manager upload:videoPOR]; 

S3TransferManager se ejecuta de forma asíncrona. Puede encontrar más información en él here.

1

Sé que esta pregunta es un poco antigua, pero acabo de encontrar el mismo problema y quería compartir la solución que encontré en: https://github.com/0i0/iOS-Amazon-S3-upload-service.

Como han mencionado las personas, si llama y carga sus datos fuera del hilo principal, entonces necesita asegurarse de que su hilo permanezca activo. Una forma de hacerlo es con NSRunLoops. En el siguiente código, vemos que el ciclo do-while accederá al ciclo de ejecución del subproceso actual y persistirá el subproceso hasta que se complete la carga.

-(void)uploadFileWithData:(NSData *)data 
       fileName:(NSString *)fileName 
       progress:(void (^)(NSInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progressCallback 
        success:(void (^)(id responseObject))successCallback 
        failure:(void (^)(NSError *error))failureCallback 
{ 

    progress = progressCallback; 
    success = successCallback; 
    failure = failureCallback; 

    _doneUploadingToS3 = NO; 


    AmazonS3Client *s3Client = [[AmazonS3Client alloc] initWithAccessKey:kAWSAccessKeyID withSecretKey:kAWSsecret]; 
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_async(queue, ^{ 

     NSString *pathToFile = [NSString stringWithFormat:@"%@%@",kAWSPath,fileName]; 
     // Upload image data. Remember to set the content type. 
     S3PutObjectRequest *por = nil; 
     por = [[S3PutObjectRequest alloc] initWithKey:pathToFile inBucket:kAWSBucket]; 
     por.cannedACL = [S3CannedACL publicRead]; 
     @try { 

      por.delegate = self; 
      por.contentType = @"image/jpeg"; 
      por.data = data; 

      [s3Client putObject:por]; 
     } 
     @catch (AmazonClientException *exception) { 
      _doneUploadingToS3 = YES; 
     } 


     do { 
      [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
     } while (!_doneUploadingToS3); 

     por.delegate = nil; 
    }); 

} 

-(void)request:(AmazonServiceRequest *)request didCompleteWithResponse:(AmazonServiceResponse *)response 
{ 
    _doneUploadingToS3 = YES; 
    success(response); 
} 
0

Gracias por su visión con respecto a subidas s3 de subprocesos principales. He encontrado los desencadenadores didCompleteWithResponse incluso si la carga falla y no he encontrado una manera fácil de determinar que falló. Intento cargar solo con los derechos de ObjectPut para que el programa no pueda disparar un ObjectGet para verificar si el archivo existe.

Cuestiones relacionadas