1

私は、次のディスパッチキューに私のアプリを持っている:メインスレッドの競合/タイミングの問題 - GCD - iPhone

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
dispatch_async(queue,^{ 

[activeModel freeUpMallocedData]; 

// UI Updates have to be made on the main thread, so request from GCD. 

dispatch_queue_t queue = dispatch_get_main_queue(); 
dispatch_async(queue,^{ 

[mainViewController removeTidyUpScreen]; 
[mainViewController showSceneList]; 
[activeModel release]; 

}); 
}); 

freeUpMallocedData方法は、UIの進捗状況表示を更新します。

- (void) freeUpMallocedData { 

// Calculate the percentage increase for each item in the pointerStorageArray as it is released so we can update the Progress Screen. 

float arrayCount = [pointerStorageArray count]; 
float incrementCounter = 1/arrayCount; // Caculates 1% of pointerStorageArray 
float newValue = incrementCounter; 
int stepCounter = 0; 

NSString * message; 

// Now iterate through the pointerStorageArray and free all malloced memory. 

for (NSValue * value in pointerStorageArray) { 

    stepCounter ++; 
    newValue = newValue + incrementCounter; 

    message = [NSString stringWithFormat:@"Freeing Up Memory (%d of %d) ...", stepCounter, (int)arrayCount]; 

    free(value); 

    [self tidyUpProgress:message amount:newValue]; 

} 

} 

tidyUpProgress方法その後、実行をメインスレッドで

- (void) tidyUpProgress: (NSString *) progressMsg amount: (float) amount { 
if (tidyUpMonitorDelegate) { 
    tidyUpProgressMsg = progressMsg; 
    tidyUpProgressAmount = amount; 
    [tidyUpMonitorDelegate performSelectorOnMainThread:@selector(model3DTidyUpProgressUpdate) withObject:nil waitUntilDone:NO]; 
} 
} 

- (void) model3DTidyUpProgressUpdate { 
progressView.progress = app.activeModel.tidyUpProgressAmount; 
loadingStatus.text = app.activeModel.tidyUpProgressMsg; 
} 

freeUpMallocedDataメソッドが完了すると、アプリケーションがクラッシュするという問題があります。これは、私の最初のディスパッチ・キューがメイン・キューを要求するために移動し、アクティブ・ビューを解放するためです。これは、最後のアップデートを実行する前にtidyUpMonitorDelegateからスレッドをハイジャックしているように見えます。メインスレッドを戻すと、activeViewが解放されたため、model3DTidyUpProgresUpdateメソッドが現在のクラスの変数へのアクセスを要求しているので、割り当て解除されました。

誰もこのタイミングの問題を解決する方法についてアドバイスできますか?

ありがとうございます。

答えて

3

だけの思考 - 派遣内の変数の名前を変更してみてください。

dispatch_queue_t mainqueue = dispatch_get_main_queue(); 
dispatch_async(mainqueue,^{ 
+0

どちらですか? tidyUpMonitorDelegateのものか、それとももう1つですか? – GuybrushThreepwood

+0

私はあなたのためのコードを追加しました... –

+0

ああそれは動作します!あなたは天才です - とてもシンプルな何か - ありがとう! – GuybrushThreepwood

-3
  • これは間違った方法である:

    フロートarrayCount = [pointerStorageArrayカウント]。

-correct方法:

NSUinteger arrayCountInt = [pointerStorageArray count]; 
NSNumber *arrayCountNumber = [NSNumber numberWithUnsignedInteger:arrayCountInt] 
float arrayCount = [arrayCountNumber floatValue]; 
+3

は実際に、それは完全に有効であり、ここに示したすべての余分な手順は、に、不要なです。さらに、この回答は質問の問題に対処していません。 – gschandler

+0

これまでのようにタイプ変換にいくつかの奇妙なエラーがあったので、それを試してみることをお勧めします – user170317

0

あなたはメインスレッドでタスクをスケジュールするために、2つの異なるメカニズムを使用します。dispatch_asycとperformSelectorInMainThread:withObject:waitUntilDone :.各メカニズムは、独自のキューを使用します。このキューは、メイン実行ループによって読み取られます。

これらのキューが読み取られる順序は未定義です。したがって、performSelectorInMainThread:withObject:waitUntilDoneによってスケジュールされたタスクは、どのタスクが最初にスケジュールされたかに関係なく、dispatch_asyncでスケジュールされたタスクの後(またはその前に)実行できます。

dispatch_asyncを使用するには、tidyUpProgress:を更新する必要があります。その後、注文は保証されます。

さらに、オブジェクトを解放した後、そのオブジェクトへの参照を保持する変数を常に無効にする必要があります。

+0

ありがとうございます - でも助けてくれない - 私がtidyUpProgressを次のように変更しても、同じ問題があります。dispatch_queue_t queue = dispatch_get_main_queue() dispatch_async(キュー、^ { [tidyUpMonitorDelegate model3DTidyUpProgressUpdate]; }); } – GuybrushThreepwood

関連する問題