2011-02-10 21 views
1

從我的主線程中,我啓動了一個圖像加載器方法方法-A(如下)。問題是,如果方法-A未在完成調用時發生新的方法-A,則圖像加載從頭開始。如何從後臺線程中獲取/設置全局變量(BOOL)? (Xcode)

我想要做的是,消除任何方法-A被同時以前方法-A通話還在做着工作提出所謂的......就我(嘗試)現在做一個簡單的全局BOOL變量(BOOL imageLoaderBusy),並使用它來跟蹤方法-A是否仍在工作(如下所示)。

問題是,變量似乎有時會被忽略,並且新的方法-A調用是不受歡迎的開始...我不知道。也許有一種特殊的方式需要創建全局變量以使它們在多個線程中可訪問/有效?

有人能告訴我我做錯了什麼嗎?謝謝。

//Method-A called like this: 

[self performSelectorInBackground:@selector(loadPagesWithGraphics:) withObject:nil]; 


//Method-A 

-(IBAction)loadPagesWithGraphics:(id)sender{ 

    NSAutoreleasePool *arPool = [[NSAutoreleasePool alloc] init]; 

    if(!imageLoaderBusy){ 

    imageLoaderBusy = YES; 

     // Load Images 

     } 

     imageLoaderBusy = NO; 

     [arPool release]; 
} 

在此先感謝。

+0

請注意,您的變量不應該是全局的。它應該是一個實例變量,因爲你的方法是一個實例方法,並且圖像加載可能指的是實例存儲/引用的圖像。 – 2011-02-10 09:53:34

+0

@Bavarious感謝這個信息,因爲我仍然對變量和多線程的確切機制缺乏清晰的理解。 – m0rtimer 2011-02-14 01:52:16

回答

1

試圖改變這種方式作爲一個實例變量或全局變量,如果多個線程可以寫入該變量同時,你需要鎖定那段代碼。例如,

-(IBAction)loadPagesWithGraphics:(id)sender{ 
    @synchronized(self) { 
     if (imageLoaderBusy) return; 
     imageLoaderBusy = YES; 
    } 

    NSAutoreleasePool *arPool = [[NSAutoreleasePool alloc] init]; 
    // Load Images 
    imageLoaderBusy = NO; 
    [arPool release]; 
} 

假設方法的兩個處決線程A和B同時發生,以及第一獲得鎖,所以線程B等待被釋放鎖。從A的角度來看,imageLoaderBusy == NO因此它不返回,設置imageLoaderBusy = YES,並釋放鎖定。

由於鎖已被釋放,線程B可以開始執行。它檢查imageLoaderBusy,並且由於線程A已經將其設置爲YES,該方法立即

線程A前進到加載圖像,並設置imageLoaderBusyNO返回螺紋B.。

請注意,這意味着如果再次在某個線程中調用該方法,它將被執行並再次加載圖像。我不確定這是否是您的預期行爲;如果不是,則需要再次檢查以確定圖像是否已加載。例如,

-(IBAction)loadPagesWithGraphics:(id)sender{ 
    if (imagesHaveBeenLoaded) return; 

    @synchronized(self) { 
     if (imageLoaderBusy) return; 
     imageLoaderBusy = YES; 
    } 

    NSAutoreleasePool *arPool = [[NSAutoreleasePool alloc] init]; 
    // Load Images 
    [arPool release]; 

    imageLoaderBusy = NO; // not strictly necessary 
    imagesHaveBeenLoaded = YES; 
} 

您不需要擁有@synchronize塊內的所有方法。事實上,關鍵部分通常應該保持很小,特別是如果將鎖應用於整個物體(self)。如果整個方法都是關鍵部分,則線程B必須等到所有圖像加載後才注意到另一個線程已經忙/已經加載了圖像。

1

Method-a調用setter是你的主線程設置BOOL

做到這一點的方法是:不管一個變量的

-(IBAction)loadPagesWithGraphics:(id)sender{ 
    if(imagesDidLoad) return; 

    @synchronized(self) { 

     NSAutoreleasePool *arPool = [[NSAutoreleasePool alloc] init]; 

     // Load Images 

     [arPool release]; 

     //set global ivar 
     imagesDidLoad = YES; 
    } 
} 

和方法-A

添加

-(void) methodA { 
    if(!imagesDidLoad) 
     [self performSelectorInBackground:@selector(loadPagesWithGraphics:) withObject:nil]; 
} 
+0

感謝您的快速回答托馬斯。這涵蓋了設置。變量的獲得情況如何?還是可以這樣做呢? – m0rtimer 2011-02-10 09:24:04

2

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait