2012-12-21 95 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