NSCondition -> Цель C - PullRequest
       1

NSCondition -> Цель C

3 голосов
/ 06 июня 2011

Я новичок в Objective-C.В настоящее время я работаю с потоками.

Я должен сделать синхронное выполнение потоков.Я использую NSInvocationOperaion для создания потока.

У меня есть два потока.Мне нужно дождаться 1-го потока, чтобы сообщить о событии или тайм-аут.Сообщение о событии может быть сделано с помощью NSConditionLock.Как сигнализировать тайм-аут.Я не мог использовать waitUntilDate метод здесь, поскольку время ожидания не является фиксированным значением.Есть ли способ сделать это?

EDITED

main.m
------
#import "PseudoSerialQueue.h"
#import "PseudoTask.h"

int main()
{
    PseudoSerialQueue* q = [[[PseudoSerialQueue alloc] init] autorelease];
    [q addTask:self selector:@selector(test0)];
    [q addTask:self selector:@selector(test1)];
    [q addTask:self selector:@selector(test2)];
    [q quit];
    return 0;
}

PseudoTask.h
-----------------

#import <Foundation/Foundation.h>


@interface PseudoTask : NSObject {

    id target_;
    SEL selector_;
    id queue_;

}

@property(nonatomic,readonly)id target;

-(id)initWithTarget:(id)target selector:(SEL)selector queue:(id)queue;
-(void)exec;

@end

PseudoTask.m
-----------------

#import "PseudoTask.h"


@implementation PseudoTask

@synthesize target = target_;

-(id)initWithTarget:(id)target selector:(SEL)selector queue:(id)queue
{
    self = [super init];
    if (self) {
        target_ = [target retain];
        selector_ = selector;
        queue_ = [queue retain];
    }
    return self;
}

-(void)exec
{
    [target_ performSelector:selector_];
}

-(void)dealloc
{
    [super dealloc];
    [target_ release];
    [queue_ release];
}

@end


PseudoSerialQueue.h
----------------------------

#import <Foundation/Foundation.h>
#import "PseudoTask.h"

@interface PseudoSerialQueue : NSObject {

    NSCondition* condition_;
    NSMutableArray* array_;
    NSThread* thread_;

}

-(void)addTask:(id)target selector:(SEL)selector;

@end

PseudoSerialQueue.m
----------------------------

#import "PseudoSerialQueue.h"

@implementation PseudoSerialQueue

-(id)init
{
    self = [super init];
    if (self) {
        array_ = [[NSMutableArray alloc]init];
        condition_ = [[NSCondition alloc]init];
        thread_ = [[NSThread alloc] initWithTarget:self selector:@selector(execQueue) object:nil];
        [thread_ start];
    }
    return self;
}

-(void)addTask:(id)target selector:(SEL)selector
{
    [condition_ lock];
    PseudoTask* task = [[PseudoTask alloc] initWithTarget:target selector:selector queue:self];
    [array_ addObject:task];
    [condition_ signal];
    [condition_ unlock];
}

-(void)quit
{
    [self addTask:nil selector:nil];
}

-(void)execQueue
{
    for(;;)
    {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc]init];

        [condition_ lock];

        if (array_.count == 0) {
            [condition_ wait];
        }

        PseudoTask* task = [array_ objectAtIndex:0];
        [array_ removeObjectAtIndex:0];

        [condition_ unlock];

        if (!task.target) {
            [pool drain];
            break;
        }

        [task exec];
        [task release];

        [pool drain];
    }
}

-(void)dealloc
{
    [array_ release];
    [condition_ release];
    [super dealloc];
}

@end

Я не мог передать себя из main.Надеюсь, я по ошибке называю это.Ошибка: 'self' undeclared идет.

Я не мог понять - (void) exec {[target_ executeSelector: selector_];} в PseudoTask.m

target_ это не метод, а его ивар.Я не получаю никаких ошибок или предупреждений. Но я не мог понять этот код.

Я пишу то, что понял из вашей программы. Пожалуйста, исправьте меня, если я неправильно понимаю программу.

Поток execQueue создается при инициализации PseudoSerialQueue и ожидает сигнала от метода addTask.Метод addTask вызывается в методе quit, и переданные параметры равны nil. Я не мог понять, почему следует передавать параметр nil.

Было бы полезно, если вы объясните это. Спасибо.

Ответы [ 2 ]

2 голосов
/ 06 июня 2011

Вы имеете в виду NSCondition ?Вы можете использовать waitUntilDate: как относительное время.

[condition lock];
// wait 5 seconds. 
[condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:5]];
[condition unlock];

РЕДАКТИРОВАНИЕ:

Мой класс PseudoSerialQueue должен вызываться из класса, производного от NSObject, как показано ниже.

@interface Test : NSObject
@end

@implementation Test
- (void)test0
{
}

- (void)test1
{
}

- (id)init
{
    self = [super init];
    return self;
}

- (void)exec
{
    PseudoSerialQueue *q = [[PseudoSerialQueue alloc] init];
    [q addTask:self selector:@selector(test0)];
    [q addTask:self selector:@selector(test1)];
    [q addTask:self selector:@selector(test0)];
    [q quit];
}
@end

Вы можете вызвать его из главной функции.

Test *test = [[Test alloc] init];
[test exec];

Я не мог понять, почему передать нулевой параметр.

Я выбрал его только для сообщения о выходе из цикла в PseudoSerialQueue.

0 голосов
/ 06 июня 2011

Пусть 1-й поток сигнализирует о 2-м в обоих случаях;затем во втором потоке вы можете указать, в каком случае вы используете какой-либо флаг только для чтения в 1-м контроллере или в вашей модели (скажем, isDataAvailable).

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