2011-10-11 293 views
1

我是新來的異步編程。我有一個被調用的異步方法的C#DLL,接受函數指針(委託)並在計算「結果」後調用此回調函數。異步回調

public delegate void CreatedDelegate(Foo result); 

public void CreateAsync(CreatedDelegate createdCallback) 
    { 
     Task t = Task.Factory.StartNew(() => 
             { 
             Foo result = ... 
             createdCallback(result); 
             }); 
    } 

類型的代表回調「CreatedDelegate」是(在我的情況下)的函數的指針的C++/CLI方法與結果的工作原理。

void CreatedCallback(Foo^ result) 
{ 
    // do something with result 
} 

所以這個異步概念似乎在大多數情況下工作得很好,但有時候我會遇到一些錯誤。如果使用不同的計算工作多次調用函數「CreateAsync」,那麼我怎麼能實現它,調用「CreatedCallback」的結果調用是否與最初調用「CreateAsync」的順序相同?爲了使它更清楚:即使後續調用「CreateAsync」的速度更快,並且實際上會更早地調用回調,第一次調用「CreateAsync」應導致第一次調用「CreatedCallback」。

也許這可以通過一次只允許一個活動的新線程在異步「CreateAsync」中完成?

+0

這不是如何線程的作品,從一個以上的,並讓他們以不可預知的方式完成無序的設計。如果這是一個問題,請使用生產者/消費者模式。 –

回答

1

要處理的回調,從而,你需要執行的工作項目排隊一些。最簡單的方法可能是使用BlockingCollection類型(請參閱MSDN documentation)。

而不是調用回調,您CreateAsync方法將(與回調一起)添加任務到隊列:

// Queue to keep tasks and their callbacks 
private BlockingCollection<Tuple<Task<Foo>, CreatedDelegate>> 
    queue = new BlockingCollection<Tuple<Task<Foo>, CreatedDelegate>>() 

public void CreateAsync(CreatedDelegate createdCallback) { 
    Task<Foo> t = Task.Factory.StartNew(() => { 
     Foo result = ... 
     return result; }); 
    queue.Add(Tuple.Create(t, createdCallback)); 
    // .. 
} 

這隻會任務和回調添加到隊列 - 實際調用回調,你需要的是等待隊列中的任務的另一個任務(按它們被添加的順序),並調用回調:

Task.Factory.StartNew(() => { 
    while(true) { // while you keep calling 'CreateAsync' 
    // Get next task (in order) and its callback 
    Tuple<Task<Foo>, CreatedDelegate> op = queue.Take(); 
    // Wait for the result and give it to callback 
    op.Item2(op.Item1.Result); 
    } 
} 
+0

Thx,我會盡快嘗試。 – Michbeckable

0

如果順序很重要,那麼使用線程可能會更好:

thread queue = empty 
for each task 
{ 
    if there are no free 'cpu' 
    wait on first thread in queue 
    remove thread from queue 
    call delegate 

    create thread 
    add thread to queue 
} 

while queue has threads 
    wait on first thread in queue 
    remove thread from queue 
    call delegate 
+0

Thx,這可能是重點。這是否被集成在「CreateAsync」中,擺脫了Task.Factory.StartNew ...? – Michbeckable

+0

您的CreateAsync是「創建線程/添加到隊列」位。 – Skizz