顯示具有 Thread 標籤的文章。 顯示所有文章
顯示具有 Thread 標籤的文章。 顯示所有文章

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(0, 0), {
    self.doSomething1()
    self.doSomething2()
    self.doSomething3()
});

<Object-C>
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
    [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停止運轉。


【專案範例】

2014年8月15日 星期五

async Thread programmatically using Swift and Object-C language

【說明】

async Thread,非同步執行緒,使用function找空閒的queue去執行次執行緒,使主執行緒可以順利的執行。


最常用在從網路上下載資料時,為了避免下載速度慢而影響了UI的回應,所以用次執行緒去做下載的動作,如此一來就可以保持主執行緒的執行順暢。

有點類似像是將工作移至背景執行的感覺。

此份筆記將紀錄如何實現async Thread。


【專案開發步驟】

建立專案:

使用Single View Application模板建立一個名為thread的專案,使用iPhone裝置。

設計使用者介面:

替View加入兩個Button,一個UIActivityIndicator,如下圖所示。

設計使用者介面
 修改ViewController:

建立中斷執行緒的function,如下所示,我們以執行執行緒的method(sleepForTimeInterval)來模擬主執行緒被中斷。

<Swift>
func doSomething1() {
    NSThread.sleepForTimeInterval(1.0)
}
func doSomething2() {
    NSThread.sleepForTimeInterval(2.0)
}
func doSomething3() {
    NSThread.sleepForTimeInterval(3.0)
}
func doSomething4() {
    NSThread.sleepForTimeInterval(4.0)
}
func doSomething5() {
    NSThread.sleepForTimeInterval(5.0)
}

<Object-C>
@interface ViewController ()
-(void)doSomething1;
-(void)doSomething2;
-(void)doSomething3;
-(void)doSomething4;
-(void)doSomething5;
@end

@implementation ViewController
-(void)doSomething1 {
    [NSThread sleepForTimeInterval:1.0];
}
-(void)doSomething2 {
    [NSThread sleepForTimeInterval:2.0];
}
-(void)doSomething3 {
    [NSThread sleepForTimeInterval:3.0];
}
-(void)doSomething4 {
    [NSThread sleepForTimeInterval:4.0];
}
-(void)doSomething5 {
    [NSThread sleepForTimeInterval:5.0];
}
@end

撰寫當按鈕按下後的function,如下所示。

<Swift>
@IBAction func click(sender: UIButton) {
    sender.enabled = false
    activityIndicator.startAnimating()
        
    dispatch_async(dispatch_get_global_queue(0, 0), {
        self.doSomething1()
        self.doSomething2()
        self.doSomething3()
        self.doSomething4()
        self.doSomething5()
            
        dispatch_async(dispatch_get_main_queue(), {
            sender.enabled = true
            self.activityIndicator.stopAnimating()
        })
    })
}

<Object-C>
- (IBAction)click:(UIButton *)sender {
    sender.enabled=NO;
    [self.activityIndicator startAnimating];
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [self doSomething1];
        [self doSomething2];
        [self doSomething3];
        [self doSomething4];
        [self doSomething5];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            sender.enabled=YES;
            [self.activityIndicator stopAnimating];
        });
    });
}
當按鈕按下後將按鈕關閉。讓activityIndicator開始旋轉。使用function despatch_async找空閒的queue執行次執行緒。當doSomething做完後使用function回到主執行緒去執行將按鈕開啟以及停止activityIndicator。


【執行結果】

    



【專案範例】