あなたはそれを信じることができますか? 私はこのようなループを持っています(エラーを許して、たくさんの情報と変数名を書き換えなければなりませんでした。str = str + "abc" str = "abc" + strより遅いか?
...古い例...コード下記参照、
を編集し、私はstr = str + "Blah \(odat.count)"
にそれらの中間のstr = "Blah \(odat.count)" + str
タイプのラインを変更した場合、UIが停止して磨くと私はカラーホイールを取得します。 NSTextFieldは最初のself.display.string...
になりますが、その後フリーズします。
私はマルチスレッドの初心者ですので、私の方法を修正してください。うまくいけば私は何を望むのか分かります。
作業バージョンもちょっと面倒ですが、決して実際にはフリーズすることはできません。ここ
完全実施例である: 典型的な値は、n = 70、VAR3 = 7
EDITです。テキストビュー、進行状況バー、およびボタンをリンクするだけです。主な機能を変更してみてください。
//
// Controllers.swift
//
//
import Cocoa
class MainController: NSObject {
@IBOutlet var display: NSTextView!
@IBOutlet weak var prog: NSProgressIndicator!
@IBAction func go1(sender: AnyObject) {
theRoutine(70)
}
@IBAction func go2(sender: AnyObject) {
theRoutine(50)
}
class SomeClass {
var x: Int
var y: Int
var p: Double
init?(size: Int, pro: Double) {
x = size
y = size
p = pro
}
}
func theRoutine(n: Int) {
prog.hidden = false
prog.doubleValue = 0
prog.maxValue = 7 * 40
let priority = DISPATCH_QUEUE_PRIORITY_HIGH
dispatch_async(dispatch_get_global_queue(priority, 0)) {
self.theFunc(n, var1: 0.06, var2: 0.06, var3: 7)
self.theFunc(n, var1: 0.1*log(Double(n))/Double(n), var2: 0.3*log(Double(n))/Double(n), var3: 7)
dispatch_async(dispatch_get_main_queue()) {
self.prog.hidden = true
self.appOut("done!")
}
}
}
//This doesn't
// func theFunc(n: Int, var1: Double, var2: Double, var3: Int) {
// var m: AnEnum
// var gra: SomeClass
// var p = var1
// for _ in 0...(var3 - 1) {
// var str = "blah \(p)\n"
// for _ in 1...20 {
// gra = SomeClass(size: n, pro: p)!
// m = self.doSomething(gra)
// switch m {
// case .First(let dat):
// str = str + "Blah:\n\(self.arrayF(dat, transform: {"blah\($0)blah\($1)=blah"}))" + "\n\n" + str
// case .Second(let odat):
// str = str + "Blah\(odat.count) blah\(self.arrayF(odat, transform: {"bl\($1)"}))" + "\n\n" + str
// }
// dispatch_async(dispatch_get_main_queue()) {
// self.prog.incrementBy(1)
// }
// }
// dispatch_async(dispatch_get_main_queue()) {
// // update some UI
// self.display.string = str + "\n" + (self.display.string ?? "")
// }
// p += var2
// }
// }
//This works
func theFunc(n: Int, var1: Double, var2: Double, var3: Int) {
var m: AnEnum
var gra: SomeClass
var p = var1
for _ in 0...(var3 - 1) {
var str = "blah \(p)\n"
for _ in 1...20 {
gra = SomeClass(size: n, pro: p)!
m = self.doSomething(gra)
switch m {
case .First(let dat):
str = "Blah:\n\(self.arrayF(dat, transform: {"blah\($0)blah\($1)=blah"}))" + "\n\n" + str
case .Second(let odat):
str = "Blah\(odat.count) blah\(self.arrayF(odat, transform: {"bl\($1)"}))" + "\n\n" + str
}
dispatch_async(dispatch_get_main_queue()) {
self.prog.incrementBy(1)
}
}
dispatch_async(dispatch_get_main_queue()) {
// update some UI
self.display.string = str + "\n" + (self.display.string ?? "")
}
p += var2
}
}
func doSomething(G: SomeClass) -> AnEnum {
usleep(30000)
if drand48() <= G.p {
return AnEnum.First([0, 0])
} else {
return AnEnum.Second([1, 1, 1])
}
}
enum AnEnum {
case First([Int])
case Second([Int])
}
func appOut(out: String?) {
if out != nil {
display.string = out! + "\n\n" + (display.string ?? "")
}
}
func arrayF(array: [Int], transform: (index: Int, value: Int) -> String) -> String {
let arr = Array(0...(array.count - 1))
return "[\(arr.map{transform(index: $0, value: array[$0])}.joinWithSeparator(", "))]"
}
}
これらのコード行がバックグラウンドスレッド上にある場合、あなたが同時に 'str'に書き込み読み込みをしない限り、あなたのUIはフリーズしません。あなたの問題がどこにあるのかと思うので、 'str'が終了したことを知るまで、' self.display.string = str + "\ n" +(self.display.string ?? "")をディスパッチしないでください。これは、原子が目的のCで便利になった場所です。 – Knight0fDragon
もちろん、それがうまくいくと信じています。しかし、あなたの問題を調査するために、*自己完結型の例が非常に役に立ちます。 –
私には何かがありませんが、実際にtheFuncを呼び出すのは何ですか? – Knight0fDragon