2011-11-23 73 views
39

以下this question,我想實現一個使用TPL的異步方法,並試圖遵循TAP指導方針。在哪裏定義回調基於任務的異步方法

我希望我的異步方法在完成時執行回調。據我所見,有三種方法可以做到這一點。

1)回調手動在我的任務委託

public Task DoWorkAsync(DoWorkCompletedCallback completedCallback) 
{ 
    return Task.Factory.StartNew(
    { 
     //do work 

     //call callback manually 
     completedCallback(); 
    }); 
} 

2)指定的回調在任務委託

public Task DoWorkAsync(DoWorkCompletedCallback completedCallback) 
{ 
    return Task.Factory.StartNew(
    { 
     //do work 
    } 
    ).ContinueWith(completedCallback); //assign callback to Task 
} 

3到任務)指定的回調在呼叫者

public Task DoWorkAsync() 
{ 
    return Task.Factory.StartNew(
    { 
     //do work 
    }); 
} 

public void SomeClientCode() 
{ 
    Task doingWork = DoWorkAsync(); 
    doingWork.ContinueWith(OnWorkCompleted); 
} 

到任務我的直覺是3更正確,因爲它將方法的回調解耦,意味着客戶端代碼可以以任何它認爲合適的方式(使用回調,輪詢等)來管理任務,這似乎是任務的全部內容。但是,如果DoWorkAsync()在客戶端代碼掛鉤其回調之前完成其工作,會發生什麼情況?

有沒有一個普遍接受的方法來做到這一點,或者它是全新的?

做2)超過1)有沒有什麼好處?

回答

28

普遍接受的方式是3

TPL的用戶一般都知道,他們可以繼續使用ContinueWith任務。 1和2提供相同的功能,但具有非標準接口;用戶必須弄清代表參數的含義以及通過的內容如果他們不想繼續 - 儘管該方法仍然返回可以以標準方式繼續的任務。

+4

謝謝,這是有道理的。將與3一起工作。但是,如果任務在連接代理被連接之前完成,會發生什麼情況?它仍然被叫?我發現文檔有點模糊。 – GazTheDestroyer

+3

是的,它被調用。 – dtb

+0

我對示例3有疑問。如果SomeClientCode()在ui線程(WPF)上運行,OnWorkCompleted也會在ui線程上運行嗎?或者是異步工作的同一個線程? –