내가 궁금한 점은 cancel/cancelAllOperations/.isCancelled를 GCD로 시작한 스레드와 함께 사용할 수 있습니까?cancel/isCancelled를 GCD/dispatch_async와 함께 사용할 수 있습니까?
현재 백그라운드 프로세스를 취소하기 위해 플래그로 부울을 사용합니다.
취소 버튼을 잡을 수 있도록 (또는 프로세서가 작동 중임을 나타 내기 위해 무언가를 움직일 수 있도록) UI 반응성을 유지하면서 백그라운드에서 많은 처리를하고 싶다고 가정 해 보겠습니다. 여기에 ...이 모두가 완벽하게 작동
#define CHECKER if (pleaseAbandonYourEfforts == YES) \
{NSLog(@"Amazing Interruption System Working!");return;}
를 ... 우리가 그것을 할 방법
@interface AstoundingView : UIView
{
BOOL pleaseAbandonYourEfforts;
blah
}
@implementation AstoundingView
//
// these are the foreground routines...
// begin, abandon and all-done
//
-(void)userHasClickedToBuildASpaceship
{
[YourUIStateMachine buildShip];
[self procedurallyBuildEnormousSpaceship];
}
-(void)userHasClickedToAbandonBuildingTheSpaceship
{
[YourUIStateMachine inbetween];
pleaseAbandonYourEfforts = false; // that's it!
}
-(void)attentionBGIsAllDone
{
// you get here when the process finishes, whether by completion
// or if we have asked it to cancel itself.
[self typically setNeedsDisplay, etc];
[YourUIStateMachine nothinghappening];
}
//
// these are the background routines...
// the kickoff, the wrapper, and the guts
//
// The wrapper MUST contain a "we've finished" message to home
// The guts can contain messages to home (eg, progress messages)
//
-(void)procedurallyBuildEnormousSpaceship
{
// user has clicked button to build new spaceship
pleaseAbandonYourEfforts = FALSE;
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
^{ [self actuallyProcedurallyBuildInBackground]; }
);
// as an aside, it's worth noting that this does not work if you
// use the main Q rather than a global Q as shown.
// Thus, this would not work:
// dispatch_async(dispatch_get_main_queue(), ^{ ...; });
}
-(void)actuallyProcedurallyBuildInBackground
{
// we are actually in the BG here...
[self setUpHere];
// set up any variables, contexts etc you need right here
// DO NOT open any variables, contexts etc in "buildGuts"
// when you return back here after buildGuts, CLEAN UP those
// variables, contexts etc at this level.
// (using this system, you can nest as deep as you want, and the
// one CHECKER pseudocall will always take you right out.
// You can insert CHECKERs anywhere you want.)
[self buildGuts];
// Note that any time 'CHECKER' "goes off', you must fall-
// through to exactly here. This is the common fall-through point.
// So we must now tidy-up, to match setUpHere.
[self wrapUpHere];
// when you get to here, we have finished (or, the user has cancelled
// the background operation)
// Whatever technique you use,
// MAKE SURE you clean up all your variables/contexts/etc before
// abandoning the BG process.
// and then you must do this......
// we have finished. it's critical to let the foreground know NOW,
// or else it will sit there for about 4 to 6 seconds (on 4.3/4.2)
// doing nothing until it realises you are done
dispatch_sync(
dispatch_get_main_queue(),
^{[self attentionBGIsAllDone];} // would setneedsdisplay, etc
);
return;
}
-(void)buildGuts
{
// we are actually in the BG here...
// Don't open any local variables in here.
CHECKER
[self blah blah];
CHECKER
[self blah blah];
CHECKER
[self blah blah];
// to get stuff done from time to time on the UI, something like...
CHECKER
dispatch_sync(
dispatch_get_main_queue(),
^{[supportStuff pleasePostMidwayImage:
[UIImage imageWithCGImage:halfOfShip] ];}
);
CHECKER
[self blah blah];
CHECKER
[self blah blah];
CHECKER
[self blah blah];
for (i = 1 to 10^9)
{
CHECKER
[self blah blah];
}
CHECKER
[self blah blah];
CHECKER
[self blah blah];
CHECKER
[self blah blah];
return;
}
및 CHECKER는 플래그가 true를 확인할 것보다 아무것도 더하지 않습니다.
하지만 ........ GCD 사용과 관련하여 cancel/cancelAllOperations/.isCancelled를 사용할 수 있습니까?
여기에 이야기가 있습니까? 건배.
PS -이 "여섯 부분"배경 템플릿을 사용하는 모든 초보자 용.
주 BJ는 아래의 강조로, 당신은 BG 과정에서 휴식 할 때마다 ... 그
당신이 열려있는 모든 변수를 정리해야합니다!
나의 관용구에서는 "setUpHere"에 모든 변수, 컨텍스트, 메모리 등을 할당해야합니다. 그리고 당신은 "wrapUpHere"에서 그들을 공개해야합니다. (이 관용구는 BG에있는 동안 깊고 깊게 간다면 계속 작동합니다.)
또는 BJ가 보여준 것과 정확하게 일치시켜야합니다. (BJ의 방법을 사용하는 경우 더 깊게 들어가면 조심하십시오.)
사용하는 방법은 BG 프로세스를 벗어날 때 열려있는 변수/컨텍스트/메모리를 정리해야합니다. 누군가가 도움이되기를 바랍니다.
나는 당신이 단일 복귀 지점에 대한 나의 요점을 놓쳤다 고 생각합니다. 'buildGuts' 메쏘드에 임시 객체를 할당했다면 메쏘드를 종료하고 그 객체에 대한 포인터를 잃기 전에 그 메쏘드에서 메쏘드를 해제해야합니다. –
단일 반환 지점에 대한 내 진술을 명확히하는 또 다른 업데이트를 추가했습니다. 당신의'self는 빠르게 활을 감싼다.'call *은 필요한 모든 메모리 관리를 처리 할 수없고,'buildGuts' 메소드가 그것을 수정하지 않은 후에 특정 메소드가 실행되도록 보장 할 수 없다. 하나의 리턴 포인트를 언급 할 때, 메소드가 종료 될 수있는 유일한 장소가 있음을 의미했습니다. 구현시, 그것은'CHECKER' 매크로가 사용되는 곳이면 어디에서나 빠져 나올 수 있습니다. 그것은 단일 반환 지점이 아닙니다. –
안녕하세요. BJ, 코드 예제에서 건배를 설명하는 몇 가지 설명을 추가했습니다. – Fattie