2014年8月18日 星期一

Group async Thread programmatically using Swift and Object-C language

【說明】

我們已經會了使用一個次執行緒來執行工作,避免主執行緒被中斷掉。現在我們要使用兩個次執行緒來加快我們次執行緒的執行速度,而要用dispatch_group的方式將兩個次執行緒包在一起,如果畫成圖如下所示。

比較:
只有一個次執行緒所執行的時間需要15秒。
有兩個次執行緒所執行的時間僅需要9秒。

【專案開發流程】

這份筆記僅修改開始執行次執行緒動作按鈕所觸發的func,其餘的步驟請參考這裡

修改按鈕觸發的func:

將以下程式碼替換掉原先在func內的程式,如下所示。

<Swift>
sender.enabled = false
activityIndicator.startAnimating()
var startDate: NSDate = NSDate.date()

<Object-C>

sender.enabled=NO;
[self.activityIndicator startAnimating];
NSDate *startDate = [NSDate date];
將按鈕關閉,不允許只用者使用。設定activityIndicator開始轉動。設立一個變數紀錄現在的時間。

<Swift>
var group: dispatch_group_t = dispatch_group_create()

<Object-C>
dispatch_group_t group = dispatch_group_create();
建立次執行緒的Group。

<Swift>
dispatch_group_async(group, dispatch_get_global_queue(00), {
    self.doSomething1()
    self.doSomething2()
    self.doSomething3()
});

<Object-C>
dispatch_group_async(group, dispatch_get_global_queue(00), ^{
    [self doSomething1];
    [self doSomething2];
    [self doSomething3];
});
加入一個queue至Group內,並執行三個工作。

<Swift>
dispatch_group_async(group, dispatch_get_global_queue(0, 0), {
    self.doSomething4()
    self.doSomething5()
});

<Object-C>
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
    [self doSomething4];
    [self doSomething5];
});
加入另一個queue至Group內,並執行兩個工作。

<Swift>
dispatch_group_notify(group, dispatch_get_main_queue(), {
    var stopDate: NSDate = NSDate.date()
    var overTime: NSTimeInterval = stopDate.timeIntervalSinceDate(startDate)
    println("Action time = \(overTime)")
            
    sender.enabled = true
    self.activityIndicator.stopAnimating()
});

<Object-C>
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    NSDate *stopDate = [NSDate date];
    NSTimeInterval overTime = [stopDate timeIntervalSinceDate:startDate];
    NSLog(@"%.f", overTime);
        
    sender.enabled=YES;
    [self.activityIndicator stopAnimating];
});
當Group內的queue都工作完畢後會發送通知,我們必須要在跳回去主執行緒執行其他的工作。設立一個stopDate的變數紀錄現在的時間。overTime用來計算從startDate到stopDate的時間。印出所需要的時間。將按鈕開啟,能讓使用者再次使用。令activityIndicator停止運轉。


【專案範例】

2 則留言:

  1. func appendContent(text:NSString) {
    var str:NSMutableString = NSMutableString(string: self.textView.text)
    str.appendString("\(text)\n")
    self.textView.text = str
    var range = NSMakeRange(str.length - 1, 1)
    self.textView.scrollRangeToVisible(range)
    }

    func gcdSales() {
    var queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
    var group: dispatch_group_t = dispatch_group_create()
    dispatch_group_async(group, queue, {
    self.gcdSaleTicketWithName("gcd-1")
    })
    dispatch_group_async(group, queue, {
    self.gcdSaleTicketWithName("gcd-2")
    })
    // dispatch_group_notify(group, queue, {
    // println("票卖完了")
    // })

    dispatch_group_notify(group, dispatch_get_main_queue(), {
    println("票卖完了")
    })

    dispatch_group_leave(group)
    }

    func gcdSaleTicketWithName(name:NSString) {
    while true {
    // 同步锁synchronized要锁的范围,对被抢夺资源修改/读取的代码部分
    objc_sync_enter(Ticket.shared)
    if Ticket.shared.tickets > 0 {
    Ticket.shared.tickets--
    var str = "剩余票数:\(Ticket.shared.tickets),线程名称:\(name)"
    // 更新界面
    dispatch_sync(dispatch_get_main_queue(), {
    self.appendContent(str)
    })
    } else {
    break
    }
    objc_sync_exit(Ticket.shared)

    // 模拟线程休眠
    if name.isEqualToString("gcd-1") {
    NSThread.sleepForTimeInterval(0.2)
    } else {
    NSThread.sleepForTimeInterval(0.5)
    }
    }
    }


    为什么不加这一句“dispatch_group_leave(group)”的时候,我的demo不会执行notify里的代码,而你的demo中会执行notify中的代码
    而你的demo中却可以执行

    回覆刪除
    回覆
    1. 可否將專案寄給我,比較方便抓出問題點

      刪除