3

次のメソッドを実行しています:

MotionHandler.m

-(void)startAccelerationUpdates
{
    [motionManagerstartDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]withHandler:^(CMDeviceMotion *motion, NSError *error){.....}
}

次のように、バックグラウンドスレッドで:

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

しかし、上記のメソッドは、main Queue(メイン スレッド上にある) を使用して、バックグラウンド スレッドで呼び出しているにもかかわらず、必要な更新を実行します。私は混乱しています..?

さらに興味深いのは、バックグラウンド スレッドで上記のメソッドを再度呼び出したときに、今回は を使用してcurrent Queue、更新が得られないことです。誰かが何かを実行することの違いを説明してもらえますか:

 1. a background thread but on the main queue

 2. a background thread but on the current queue 

 3. the main thread but on the main queue  

 4. the main thread but on the current queue

現在の実装では?ありがとうございました!

4

2 に答える 2

5

やってみます。まず、NSOperationQueue クラス リファレンスによって通知されなければ、「mainQueue」が実行されるスレッドについて何も推測できませんでした。これを読むと、実際には、UI が使用する mainThread でキューが操作を実行することがわかります。そのため、そのキューに投稿された操作で UI を更新できます。明記されていませんが、runLoop によって実行されるため、これらの操作はシリアルでなければなりません (100% 確実ではありませんが、プリエンプトされる可能性もあります)。

currentQueue の目的は、実行中の操作がそのキューを特定し、そのキューで新しい操作を潜在的にキューに入れることができるようにすることです。

  1. バックグラウンド スレッドだがメイン キューにある

不可能 - NSOperation の mainQueue は常に mainThread に関連付けられています。

  1. バックグラウンド スレッドだが現在のキューにある

NSOperationQueue を作成し、それに NSOperations を追加すると、それらはキューによって管理されるバックグラウンド スレッドで実行されます。特定の操作は、どのスレッド上にあるかを照会でき、そのスレッドは実行中に変更されません。つまり、そのキューの 2 番目の操作が別のスレッドで実行される可能性があります。

  1. メインスレッドですが、メインキューにあります

参照 1)

  1. メインスレッドですが、現在のキューにあります

操作を mainQueue (常に mainThread 上にあることがわかっています) のキューに入れ、currentQueue を要求すると、mainQueue が返されます。

[NSOperationQueue currentQueue] == [NSOperationQueue mainQueue];
于 2012-08-28T13:23:47.493 に答える
4

キューとスレッドを混同しています。特に、NSOpertionQueueはGCDを使用するように書き直されているため、キューと特定のスレッドの間の接続はほとんどありません(メインスレッドの特殊なケースを除く)。

操作/ブロック/タスク(呼び出したいものは何でも)がキューに挿入され、「ワーカースレッド」がこれらをプルして実行します。メインキューを除いて、どの正確なスレッドが作業を実行するかをほとんど制御できません。 これは単純化されているため、正確には正しくありませんが、非常に高度で具体的なことをしているのでない限り、十分に真実です。

したがって、たとえば「バックグラウンドスレッドではなくメインキュー」で何かを実行することはできないため、4つのシナリオのいずれも意味がありません。

これで、メソッドstartAccelerationUpdatesはCMMotionManagerにハンドラーをメインキューに配置するように具体的に指示します。したがって、startAccelerationUpdatesが呼び出されると、実行中のスレッドで実行されますが、ハンドラーがメインスレッドで実行されるようにスケジュールされます。

少し複雑にするために、を呼び出してstartAccelerationUpdatesメソッドを呼び出していperformSelectorInBackgroundます。繰り返しますが、実際にどのスレッドが呼び出されるかはわかりませstartAccelerationUpdatesんが、メインスレッドにはなりません。

ただし、あなたの場合、そのスレッドが行っているのはstartAccelerationUpdates、モーション更新を開始している呼び出しと、メインスレッドで(メインキューを介して)処理するように指示することだけです。

さて、ドキュメントから直接、メインキューを使用してモーションイベントを処理することを思いとどまらせるための何かがあります...

処理されたイベントが高率で到着する可能性があるため、メイン操作キューを使用することはお勧めしません。

残念ながら、あなたの声明

さらに興味深いのは、バックグラウンドスレッドで上記のメソッドを再度呼び出すと、今回は現在のキューを使用しても更新がないことです。

何を試したか、どのように試したか、なぜうまくいかなかったと思うかを判断するのに十分な情報を提供していません。だから、私は推測します...それは間違っているかもしれません。

の使用についてキーを押しますthe current Queue

で代用するという意味だと思い[NSOperationQueue mainQueue]ます[NSOperationQueue currentQueue]

さて、それが何をするのか見てみましょう。メインキューを使用する代わりに、「他の」キューを使用します。どれ?さて、ドキュメントを見てみましょう:

currentQueue

現在の操作を開始した操作キューを返します。

+(id)currentQueue

戻り値

操作を開始した操作キュー。キューを判別できなかった場合はnil。

討論

実行中の操作オブジェクト内からこのメソッドを使用して、それを開始した操作キューへの参照を取得できます。実行中の操作のコンテキスト外からこのメソッドを呼び出すと、通常、nilが返されます。

ディスカッションセクションに注意してください。から呼び出された操作を実行していないときにこれを呼び出すと、ハンドラーを配置するキューがないことを意味しますNSOperationQueuenilだから、あなたは何も得られません。

NSOperationQueueメインキュー以外を使用する場合は、使用するキューを指定する必要があります。したがって、それが目的のルートである場合は、モーションイベントを処理するための独自の操作キューを作成するだけで、オフになります。

幸運を!

于 2012-08-28T13:28:07.507 に答える