0

Q1:メソッドを呼び出して、現在メインスレッドで実行されている別のメソッドの内部からバックグラウンドスレッドで実行させることはできますか?

Q2:上記の拡張として、メソッドを呼び出して、他のバックグラウンドスレッド自体で現在実行されている別のメソッドの内部からバックグラウンドスレッドで実行させることはできますか?

Q3:そして上記の最後の質問です:あるスレッド(メイン/バックグラウンド)であるオブジェクトXのインスタンスを初期化し、そのオブジェクトXのメソッドYを他のバックグラウンドスレッドで実行すると、このメソッドYは可能になりますメッセージを送信して更新しますint property(たとえば、そのオブジェクトX、またはそのような通信は不可能ですか?

私がこの最後の質問をしている理由は、私が何度も何度もそれを繰り返してきて、ここで何が悪いのか理解できないからです。

次のコードは、ゼロ加速度とゼロ度の値を返します。

MotionHandler.m

@implementation MotionHandler

@synthesize currentAccelerationOnYaxis; // this is a double

-(void)startCompassUpdates
{
    locationManager=[[CLLocationManager alloc] init];
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    locationManager.delegate=self;
    [locationManager startUpdatingHeading];
    NSLog(@"compass updates initialized");
}

-(int) currentDegrees
{
    return (int)locationManager.heading.magneticHeading;
}
-(void) startAccelerationUpdates
{
    CMMotionManager *motionManager = [[CMMotionManager alloc] init];
    motionManager.deviceMotionUpdateInterval = 0.01;
    [motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue]
                                       withHandler:^(CMDeviceMotion *motion, NSError *error)
                                       {
                                           self.currentAccelerationOnYaxis = motion.userAcceleration.y;
                                       }
    ];
}

@end

Tester.m

@implementation Tester

-(void)test
{
    MotionHandler *currentMotionHandler = [[MotionHandler alloc] init];

    [currentMotionHandler performSelectorInBackground:@selector(startCompassUpdates) withObject:nil];

    [currentMotionHandler performSelectorInBackground:@selector(startAccelerationUpdates) withObject:nil];

    while(1==1)
    {
        NSLog(@"current acceleration is %f", currentMotionHandler.currentAccelerationOnYaxis);
        NSLog(@"current degrees are %i", [currentMotionHandler currentDegrees]);
    }

SomeViewController.m

@implementation SomeViewController
-(void) viewDidLoad
{
    [myTester performSelectorInBackground:@selector(test) withObject:nil];
}
@end

ただし、次のコードは通常、これらの値を返します。

Tester.m

@interface Tester()
{
    CLLocationManager *locationManager;
    double accelerationOnYaxis;
    // more code..
}
@end

@implementation Tester

- (id) init
{
    locationManager=[[CLLocationManager alloc] init];
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    locationManager.delegate=self;
    [locationManager startUpdatingHeading];

    // more code..
}


-(void) test
{
    CMMotionManager *motionManager = [[CMMotionManager alloc] init];
    motionManager.deviceMotionUpdateInterval = 0.01;
    [motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
                                       withHandler:^(CMDeviceMotion *motion, NSError *error)
     {
         accelerationOnYaxis = motion.userAcceleration.y;
     }
     ];

     while(1==1)
    {
        NSLog(@"current acceleration is %f", accelerationOnYaxis);
        NSLog(@"current degrees are %i", locationManager.heading.magneticHeading);
    }
}

SomeViewController.m

@implementation SomeViewController

-(void) viewDidLoad
{
    [myTester performSelectorInBackground:@selector(test) withObject:nil];
}

最初のバージョンの何が問題になっていますか?デザイン的にはずっと良いように見えるので、私は本当に最初のものを使いたいです。助けてくれてありがとう!

4

2 に答える 2

1

呼び出しは、現在のオブジェクト、セレクター、およびパラメーターオブジェクトをパラメーターとして使用してのメソッドをperformSelectorInBackground:withObject:呼び出した場合と同じです(スレッドプログラミングガイド)。どこで呼び出しても、そのセレクターを実行するための新しいスレッドが作成されます。したがって、最初の2つの質問に答えるには、「はい」と「はい」を使用します。detachNewThreadSelector:toTarget:withObject:NSThread

最後の質問ですが、このオブジェクトXが両方のメソッドで同じオブジェクトである限り、Xの任意のプロパティを更新できます。ただし、これにより予期しない結果が生じる可能性があることに注意してください(つまり、同時実行プログラミングガイドを参照してください)。複数のメソッドがXのプロパティを更新している場合、値は上書きまたは無視される可能性があります。ただし、メソッドYからのみ更新し、他のすべてのメソッドから読み取る場合は、このような問題は発生しません。

于 2012-08-22T15:06:34.223 に答える
1

AppleのGrandCentralDispatchのドキュメントをご覧ください。これにより、ブロックベースの構造で複数のスレッドを使用できます。

2つの重要な機能はとdispatch_sync()ですdispatch_async()

いくつかの例:

バックグラウンドスレッドで特定のコードブロックを実行し、完了するまで待つには、次のようにします。

__block id someVariable = nil;
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    // do some heavy work in the background

    someVariable = [[NSObject alloc] init];
});

NSLog(@"Variable: %@", someVariable);

この関数は、後で使用できる変数someVariableを変更します。メインスレッドはバックグラウンドスレッドを待つために一時停止されることに注意してください。dispatch_async()それが希望しない場合は、次のように使用できます。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    // do some heavy work in the background

    NSObject *someVariable = [[NSObject alloc] init];

    // notify main thread that the work is done
    dispatch_async(dispatch_get_main_queue(), ^{
        // call some function and pass someVariable to it, it will be called on the main thread
        NSLog(@"Variable: %@", someVariable);
    });
});
于 2012-08-22T15:13:33.340 に答える