2016-08-28 4 views
1

In meinem Swift-Projekt versuche ich eine FIFO-Warteschlange (ich werde es hier eine Liste nennen, um Verwirrung zu vermeiden) in einem Hintergrund-Thread. Wenn ich dispatch_async verwende, führt dies zu einem EXC_BAD_ACCESS-Fehler, nachdem nur ein Teil der Liste ausgeführt wurde. Ich habe den Code soweit wie möglich in den folgenden Spielplatzcode vereinfacht. Wenn auf dem Spielplatz main_thread auf "true" gesetzt ist, verarbeitet der Code alle 100 Elemente in der Liste. Wenn es falsch ist, werden nur eine Handvoll Elemente verarbeitet. Wenn sich der Code in einem Projekt befindet, tritt EXC_BAD_ACCESS auf, wenn main_thread falsch ist. Offensichtlich habe ich auch versucht, eine serielle Warteschlange anzugeben, aber das scheint nicht zu helfen. Was vermisse ich oder verstehe ich nicht? Danke.Swift dispatch_async führt zu EXC_BAD_ACCESS Fehler

import UIKit 

let main_thread = false 
let serial_queue = true 

class main_class { 
    var this_list = list_class() 


    func run(){ 
     for i in 1...100 { 
      this_list.add_to_list(String(i)) 
     } 

     if main_thread { 
      this_list.process_list() 
     } else { 
      if serial_queue { 
       let my_serial_queue = dispatch_queue_create("msq", DISPATCH_QUEUE_SERIAL) 
       dispatch_async(my_serial_queue){()->Void in 
        self.this_list.process_list() 
       } 
      } else { 
       dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {() ->Void in 
        self.this_list.process_list() 
       }) 
      } 

     } 
    } 
} 

class list_class { 
    var my_list: [String] = [] 

    func add_to_list(this: String){ 
     my_list.append(this) 
    } 

    func process_list(){ 
     if my_list.count > 0 { 
      print("removing " + my_list[0]) 
      remove_from_list(my_list[0]) 
     } 
    } 

    func remove_from_list(this: String){ 
     let found = my_list.indexOf(this) 
     if found != nil { 
      my_list.removeAtIndex(found!) 
      process_list() 
     } 
    } 
} 

var blah = main_class() 
blah.run() 

Antwort

1

Ihr Haupt-Thread wird beendet, während der Hintergrund-Thread noch läuft. Haupt-Thread endet -> Prozess wird beendet.

Richten Sie etwas ein, damit die Hauptleitung blockiert, während der Hintergrund-Thread noch läuft. Verwenden Sie beispielsweise dispatch_group_wait(); zusammen mit dispatch_group_enter() und dispatch_group_leave().

+0

Ich bin offensichtlich einige ziemlich Kernkonzept fehlt hier :(Der Punkt des Setzens dispatch_async dort war so der Haupt-Thread wurde nicht blockiert. Ich bin jetzt schrecklich verwirrt. – Matt

+0

@Matt: Der Punkt von 'dispatch_async' in dort war so, dass der Hauptthread * durch diese asynchrone Arbeitsbelastung * nicht blockiert wurde. Der Hauptfaden ist dann frei, andere Sachen zu tun, wie warten auf I/O. Wenn Sie nichts anderes tun müssen, ist 'dispatch_async' sinnlos. –

+0

In einer" normalen "App wäre main beschäftigt, etwas anderes zu tun, oder auf Benutzereingaben zu warten, alles andere als enden Der Umgang mit Benutzereingaben ist wichtig und wichtig, um schnell zu reagieren, so dass Sie nicht lange arbeiten müssen . Du hast es richtig, das zu einem Hintergrund-Thread zu verschieben. Aber in Ihrem Beispiel gibt es keine Benutzereingaben für main, damit das Modell nicht relevant ist. –

0

Dank Graham Perks antworte, dass ich dispatch_group_wait brauchte - ich endete mit diesem Code funktioniert wie benötigt. Ich hatte nicht brauchen 2 Asynchron-Anrufe erwartet :(XCPlayground nur auf dem Spielplatz erforderlich war.

import UIKit 
import XCPlayground 

var GlobalMainQueue: dispatch_queue_t { 
    return dispatch_get_main_queue() 
} 
var GlobalBackgroundQueue: dispatch_queue_t { 
    return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0) 
} 

class main_class { 
    var this_list = list_class() 
    var done = "NO" 
    func run(){ 
     for i in 1...100 { 
      this_list.add_to_list(String(i)) 
     } 

     dispatch_async(GlobalBackgroundQueue){ 
      let ds_group = dispatch_group_create() 

      dispatch_group_enter(ds_group) 
      dispatch_async(GlobalMainQueue){ 
       self.this_list.process_list() 
       dispatch_group_leave(ds_group) 
      } 

      dispatch_group_wait(ds_group, DISPATCH_TIME_FOREVER) 
      dispatch_async(GlobalMainQueue){ 
       self.done = "YES" 
      } 
     } 

    } 
} 

class list_class { 
    var my_list: [String] = [] 

    func add_to_list(this: String){ 
     my_list.append(this) 
    } 

    func process_list(){ 
     if my_list.count > 0 { 
      print("removing " + my_list[0]) 
      remove_from_list(my_list[0]) 
     } 
    } 

    func remove_from_list(this: String){ 
     let found = my_list.indexOf(this) 
     if found != nil { 
      my_list.removeAtIndex(found!) 
      process_list() 
     } 
    } 
} 

var blah = main_class() 
blah.run() 
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true 
+0

Dies gehört nicht zu einer Antwort. –

+0

Warum ist das? Liegt es daran, dass der spezifische Wortlaut meiner Frage "Was fehlt mir oder nicht?" Lautet? und meine Antwort erweitert nur die Hinweise, die Graham Perks zur Verfügung gestellt hat? Ich versuche nicht, schwierig zu sein, ich verstehe einfach nicht, warum du denkst, dass es nicht dazugehört? Sollte es unter Grahams Antwort einen Kommentar geben? Ich glaube nicht, dass Code in Kommentaren enthalten sein könnte. Danke, dass Sie einem Noob-Poster geholfen haben. – Matt

Verwandte Themen