EXC_BAD_INSTRUCTION: task_thread не удалось какао - PullRequest
0 голосов
/ 18 апреля 2011

Я пишу приложение для печати сообщений, полученных с сервера. Я отключаю в другой теме функцию прослушивания:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
char *read;

do {
    chk = (int) recv(connfd, read, 1, 0);

    if(chk==-1) {
        printf("Error in recv(): connfd = %d\n",connfd );
        perror(err);
    }
    else if (chk ==0) {
        [messagesView insertText:@"\nConnection closed by remote host\n"];
        printf("Connection closed by remote host\n");
    }
    else {
        if( *read == '\n') {
            [messagesView insertText:@"\\n\n"];
            printf("\\n");
        }
        else if (*read == '\r') {
            [messagesView insertText:@"\\r\r"];
            printf("\\r");
        }
        else {
            [messagesView insertText:[NSString stringWithFormat:@"%c",*read]];
            printf("%c", *read);
        }
        printf(" -- %d\n",*read);
    }
}   while (chk>0);

[pool drain];

chk и connfd - это int, messagesView - это NSTextView *. Приложение вылетает, когда я звоню [messagesView insertText:] и получаю ошибку в заголовке. Если я прокомментирую все эти вызовы, приложение будет работать нормально, и я смогу прочитать правильное сообщение в консоли. Есть предложения?

Ответы [ 2 ]

4 голосов
/ 18 апреля 2011

Вторичные потоки не должны касаться GUI.Вам нужно будет передать информацию обратно объекту в главном потоке, чтобы обновить текстовое представление.

Из Руководства по программированию потоков :

Потоки и ваш пользовательский интерфейс
Если ваше приложение имеет графический пользовательский интерфейс, рекомендуется получать связанные с пользователем события и инициировать обновления интерфейса из основного потока вашего приложения.Такой подход помогает избежать проблем синхронизации, связанных с обработкой пользовательских событий и содержимым окна рисования.Некоторые платформы, такие как Какао, обычно требуют такого поведения, но даже для тех, которые этого не делают, сохранение этого поведения в основном потоке имеет преимущество, заключающееся в упрощении логики управления вашим пользовательским интерфейсом.

2 голосов
/ 18 апреля 2011

Я не уверен, является ли это точной причиной вашей проблемы, но это, безусловно, может быть так: вы никогда не инициализируете read, поэтому непредсказуемо перезаписываете какой-то байт в памяти вашей программы.Это должно быть что-то вроде:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
char read;

do {
    chk = (int) recv(connfd, &read, 1, 0);

    if(chk==-1) {
        printf("Error in recv(): connfd = %d\n",connfd );
        perror(err);
    }
    else if (chk ==0) {
        [messagesView insertText:@"\nConnection closed by remote host\n"];
        printf("Connection closed by remote host\n");
    }
    else {
        if( read == '\n') {
            [messagesView insertText:@"\\n\n"];
            printf("\\n");
        }
        else if (read == '\r') {
            [messagesView insertText:@"\\r\r"];
            printf("\\r");
        }
        else {
            [messagesView insertText:[NSString stringWithFormat:@"%c", read]];
            printf("%c", read);
        }
        printf(" -- %d\n", read);
    }
}   while (chk>0);

[pool drain];

Хотя, как отмечает Джош Касвелл, все эти сообщения insertText: должны быть примерно такими: [messagesView performSelectorOnMainThread:@selector(insertText:) withObject:@"\nConnection closed by remote host\n" afterDelay:0].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...