2012-12-21 98 views
0

我需要像多個異步調用

IList<Task> Ts = new List<Task>(); 
Ts.Add(GetInformationFromServer(ID)); 

創建多個異步調用但我不什麼的線程是在等待着,我從

調用所以它應該是可以做到這樣的(舊的方式之一,但有一個新的?),從另一個電話

GetInformation(string ID) { 
    while (!Finish) { 
     Thread.Sleep(100); 
    } 
    return _Information.First(a=>a.ID==ID); 
} 

我當然可以保存在變量的任務,但我該如何開始呢?我如何獲得狀態?
我想我可以在另一個線程中等待它們,但是如何檢查它們是否完成?我應該自己實施嗎?
我該如何啓動它們(我應該只使用Task.WhenAll而不等待)?

UPDATE

我想通了,我要實現我自己的方式,所以答案是怎麼樣的這種方式,但我需要使用,而不是Func鍵

/// The executed elements 
private IList<T> _ExecutedElements; 

/// The Stack over the elements to be executed 
private Stack<T> _ExecutingElements; 

/// The method to be runned 
private Func<object, Task<T>> _Method; 

/// Should the while-loop start? 
private bool _Running; 

/// The Task 
private Task<T> _Task; 

/// Construct the class 
/// <param name="Method">The function to be executed</param> 
public MultiAsync(Func<object, T> Method) { 
    _Method = Method; 
} 

/// Add an element 
/// <param name="Item">The item to be added</param> 
public void AddItem(T Element) { 
    _ExecutingElements.Push(Element); 
} 

/// Execute the method 
public async void ExecuteAsync() { 

    // Set it to start running 
    _Running = true; 

    // While there are elements left 
    while (_ExecutingElements.Count > 0) { 

     // Check if it is not running, and if it isn't break out 
     if (!_Running) { break; } 

     // The current element 
     T Element = default(T); 

     // Pop out the element, that has not been runned through 
     do { Element = _ExecutingElements.Pop(); } 
     while (!_ExecutedElements.Contains(Element)); 

     // Check if there is an element, and if there is execute the method and await it 
     if (Element != default(T)) { 
     await ExecuteMethodAsync(Element); 
     } 
    } 
} 

/// Execute the item 
/// <param name="Item">The item to be executed</param> 
/// <returns>The executed item (due to reflection in FillInformation, the Item is filled)</returns> 
public async Task<T> ExecuteItemAsync(T Item) { 

    // Check if the item has not been executed, and if it is not executed 
    if (!_ExecutedElements.Contains(Item)) { 

     // Stop the while-loop 
     _Running = false; 

     // Check if the Task is running, and if it is await it 
     if (_Task != default(Task) && !_Task.IsCompleted && !_Task.IsFaulted) { 
     await _Task; 
     } 

     // Execute the method using the specific item 
     await ExecuteMethodAsync(Item); 
    } 

    // Start the while-loop 
    ExecuteAsync(); 

    // Return the element 
    return Item; 
} 

/// Execute the method 
/// <param name="Item">The item to run</param> 
/// <returns>The Task to be executed</returns> 
private async Task ExecuteMethodAsync(T Item) { 

    // Set the Task 
    _Task = _Method.Invoke(Item) 

    // Start the task 
    T Element = await _Task; 

    // Add the item to the List 
    _ExecutedElements.Add(Element); 

    // Fill the information 
    FillInformation(Element); 
} 

調用任務是這樣的

private async void FillTasksAsync(IEnumerable<Model.Task> Tasks) { 
    _InfoLoader = new MultiAsync<Model.Task>(Tsk => { return GetTaskAsync(Tsk); }); 

    foreach (var Tsk in Tasks) { 
     _InfoLoader.AddItem(Tsk); 
    } 
} 
+0

你能更詳細地描述你的問題嗎?你使用多個任務來分解問題嗎?線程是否需要在某種狀態下同步?一般來說,最好不要在後臺線程中睡覺,而是等到工作準備就緒後再啓動任務。 –

+0

是的,我正在使用異步調用來分解問題。而且他們不會同步,因爲他們正在處理不同的對象。我也許可以使用線程或線程池,然後加入它們以在準備就緒時得到通知 – The87Boy

+1

爲什麼你不想「等待」?使用'await'是最乾淨和最受支持的解決方案。 –

回答

1

我有一篇博客文章,討論asynchronous initialization,這聽起來像你所需要的。它來自Stephen Toub的原創想法。

在這種情況下,你可以使用:

List<AsyncLazy<string>> Ts = ... 
Ts.Add(new AsyncLazy<string>(() => GetServerStringAsync(ID)); 

要啓動一個下載,你可以這樣做:

Ts[0].Start(); 

而當你需要它,你可以這樣做:

var result = await Ts[0]; 

這將(異步)等待它完成下載,如果它尚未。如果已經存在,那麼你會立即得到結果。

+0

因此,我需要將所有項目添加到列表中,並且然後使用開始所有或?我想,我可以做一次,但是我認爲我應該實施自己的班級,這一定是結果。我正在考慮一件事,也許你有權回答這個問題:是否是Task.WhenAll一次或多次執行一個? – The87Boy

+0

你需要開始每一個。 'Task.WhenAll'不同;它會返回一個「任務」,該任務在所有傳遞給它的任務完成時完成。 –

+0

好吧,它將所有任務合併到一個?
如果明天沒有人提出更好的答案,我認爲我最好創建自己的類,然後我需要一些響應來提高性能 – The87Boy