6

メインスレッドをブロックしているため、非同期関数の実行を実行する必要があり、UI を使用できません。

stackoverflow の質問を見た後、非同期関数を実行するには 3 つの方法があることがわかりました。

例:

[NSThread detachNewThreadSelector:@selector(showSpinner:) toTarget:self withObject:self.view];
// or 
[self performSelectorInBackground:@selector(showSpinner:) withObject:self.view];
// or 
NSInvocationOperation *invOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(showSpinner:) object:self.view];
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
[opQueue addOperation:invOperation];
// or 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self showSpinner:self.view];
    });
});

私の質問は、どのようにしてメインスレッドperformSelectorInBackgrounddetachNewThreadSelector戻るのですか? それらが完了したことをどのように知っていますか?

4

2 に答える 2

7

いくつかの考え:

  1. 並行性プログラミングガイドの「スレッドからの移行」を確認することをお勧めします。これは、同じガイドで前述したディスパッチキューと操作キューについて説得力のある議論をします。

  2. また、さまざまな非同期操作を詳しく調べるときは、バックグラウンドキュー/スレッドで時間のかかる作業を行うことを忘れないでください。ただし、常にUIをメインキューにディスパッチしてください。あなたのタスクshowSpinnerはUIタスクによく似ているので、バックグラウンドのキュー/スレッドでは絶対にやりたくないとだけ言っておきます。UIに関連しない「高価な」タスクがある場合は、バックグラウンドで実行しますが、UIのものがメインキューにディスパッチされることを確認してください。

  3. 余談ですが、操作キューには他のレンディションがあります。たとえば、ブロック操作などです。

    NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
    [opQueue addOperationWithBlock:^{
        // do some slow stuff in the background here
    
        // ok, now do UI stuff in the main queue
    
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [self showSpinner:self.view];
        }];
    }];
    

    これは、GCD(ディスパッチキュー)レンディションとほぼ同等です。

    dispatch_queue_t dispatchQueue = dispatch_queue_create("com.ramshad.app", 0);
    dispatch_async(dispatchQueue, ^{
        // do some slow stuff in the background here
    
        // ok, now do UI stuff in the main queue
    
        dispatch_async(dispatch_get_main_queue(), ^{
            [self showSpinner:self.view];
        });
    });
    

    操作キューとディスパッチキューの間には微妙な長所と短所がたくさんありますが(Stack Overflowの他の場所で何百回も議論されているため、ここでは取り上げないでください)、どちらも従来よりも複雑さが少なく、驚くほど豊富な非同期操作を実行できますスレッドプログラミング。

  4. スレッド対操作および/またはディスパッチキュー(私は必ずしもお勧めしません)に固執することにした場合は、スレッドプログラミングガイドを確認することをお勧めします。

于 2013-03-13T04:57:11.737 に答える
2

実行を識別して終了するには、メインスレッドのスレッドメソッドの最後にあるメソッドを呼び出しますperformSelectorInBackgrounddetachNewThreadSelector

さらに、レシーバーが実行を終了したかどうかを示すブール値を返すNSThreadプロパティを提供します。isFinished

例:

[self performSelectorOnMainThread:@selector(threadMethod) 
                       withObject:nil 
                    waitUntilDone:NO];

また

[NSThread detachNewThreadSelector:@selector(threadMethod) 
                         toTarget:self 
                       withObject:nil];

-(void)threadMethod{

    //here your implementation code
    //here call the end notification method.
    [self performSelectorOnMainThread:@selector(ThreadExecutionDone) 
                           withObject:nil 
                        waitUntilDone:YES];
}

-(void)ThreadExecutionDone{
    //end of the performSelectorInBackground or detachNewThreadSelector.
}
于 2013-03-13T03:44:44.037 に答える