2013-11-14 83 views
0

,我讀了這裏http://blog.stephencleary.com/2012/02/async-and-await.html如何確定作業異步/等待

這種引導線的狀態在這裏我得到了一些夫婦的代碼,但不是很清楚,我。

1)

public async Task DoOperationsInParallelAsync() 
{ 
    Task[] tasks = new Task[3]; 
    tasks[0] = DoOperation0(); 
    tasks[1] = DoOperation1(); 
    tasks[2] = DoOperation2(); 

    // At this point, all three tasks are running in parallel. 

    // Now, we await them all. 
    await Task.WhenAll(tasks); 
} 
在上面

我們正在創建多個任務,但假設,當所有任務運行,那麼平行DoOperation2()可完成第一和DoOperation0(),最後DoOperation1()完成。如果我想顯示消息像DoOperation2()在控制檯窗口中完成,那麼我怎麼能做到這一點。我怎麼能檢測到多個運行時哪個任務完成。

2)當我們在async/await的幫助下運行任何函數時,它會作爲後臺線程還是前臺線程運行。

3)

public async Task<int> GetFirstToRespondAsync() 
{ 
    // Call two web services; take the first response. 
    Task<int>[] tasks = new[] { WebService1(), WebService2() }; 

    // Await for the first one to respond. 
    Task<int> firstTask = await Task.WhenAny(tasks); 

    // Return the result. 
    return await firstTask; 
} 

我不明白爲什麼人寫等待的第一個響應。

//等待第一個迴應。 任務firstTask =等待Task.WhenAny(任務);

爲什麼第一個......爲什麼不是第二個,因爲兩個任務在這裏運行。

請指導我,趕走我的困惑。謝謝

+1

我認爲你的一些混亂是由語言造成的:第一個響應並不意味着第一次進入,這意味着首先響應的人將是第一次。 –

回答

1
  1. 因爲它是一個控制檯應用程序,您需要等待任務完成。以下是如何從一個任務返回一個字符串的例子:

    class WhenAny 
    { 
        public static async Task<string> GetFirstToRespondAsync() 
        { 
         // Call two web services; take the first response. 
         Task<string>[] tasks = new[] { Task1(), Task2() }; 
    
         // Await for the first one to respond. 
         Task<string> firstTask = await Task.WhenAny(tasks); 
    
         // Return the result. 
         return firstTask.Result; 
        } 
    
        private static async Task<string> Task1() 
        { 
         await Task.Delay(3000); 
         return "Task1"; 
        } 
    
        private static async Task<string> Task2() 
        { 
         await Task.Delay(1000); 
         return "Task2"; 
        } 
    } 
    

    呼叫從主要功能如下:

    static void Main(string[] args) 
    { 
        var t = WhenAny.GetFirstToRespondAsync(); 
        t.ContinueWith((taskName) => 
         { 
          string result = taskName.Result; 
          Console.WriteLine("Result: " + result); 
         }); 
    
        t.Wait(); 
        Console.ReadLine(); 
    } 
    

    這應該返回第一個完成任務,你可以訪問來自Task.Result的信息

  2. 等待一個方法本身不會創建一個額外的線程。它所做的是創建回調以避免阻塞當前線程(通常用於不阻止UI線程)。

  3. WhenAny當最早完成的操作返回時返回。這並不意味着您提供的列表中的第一個。所以,上面的代碼將始終顯示1000,即使它是第二項任務。

爲了完整起見,在這裏與WhenAll同樣的事情:

class WhenAll 
{ 

    public static async Task<string[]> WaitForAllAsync() 
    { 
     // Call two web services; take the first response. 
     Task<string>[] tasks = new[] { Task1(), Task2(), Task3() }; 

     // Wait for a tasks 
     string[] results = await Task.WhenAll(tasks); 

     // Return the result. 
     return results; 
    } 

    private static async Task<string> Task1() 
    { 
     await Task.Delay(3000); 
     return "Task1"; 
    } 

    private static async Task<string> Task2() 
    { 
     await Task.Delay(1000); 
     return "Task2"; 
    } 

    private static async Task<string> Task3() 
    { 
     await Task.Delay(5000); 
     return "Task3"; 
    } 

} 

,並呼籲它:

static void Main(string[] args) 
{ 
    var t = WhenAll.WaitForAllAsync(); 
    t.ContinueWith((task) => 
    { 
     string[] result = task.Result; 
     foreach(string taskname in result) 
     { 
      Console.WriteLine("Result: " + taskname); 
     } 
    }); 

    t.Wait(); 
    Console.ReadLine(); 

} 
+0

可以指導我如何完成時的例程名稱。這裏我們執行2例程Task1&Task2。所以從按鈕單擊我怎麼能顯示例程名稱像Task2()完成。謝謝 – Thomas

+0

ForAll或WhenAny? –

+0

在這裏你正在運行兩個任務,我想當任何任務將完成,然後任務名稱將返回到它的調用環境。 – Thomas

1

對於每個將更新進度的任務,您都可以使用ContinueWith方法。

所以......

foreach (var t in tasks) 
{ 
    t.ContinueWith(Console.WriteLine("Hey I am done")); 
} 
1

1)傳入一個回調函數

public async Task DoOperationsInParallelAsync(Action<Task<int>> completed) 
{ 
    var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 
    var tasks = new[] { DoOperation0(), DoOperation1(), DoOperation2() }; 

    var completedTasks = tasks.Select(x => x.ContinueWith(completed, uiScheduler)).ToArray(); 

    await Task.WhenAll(completedTasks); 
} 

private async void Button1_Click(object sender, EventArgs e) 
{ 
    await DoOperationsInParallelAsync(t => { 
     Label1.Text = string.Format("Task finished with {0}", t.Result); 
    }); 
} 

2)Task將在線程池運行,除非你將其指定爲長時間運行或提供TaskScheduler

3)當只有第一個結果很重要(計算是多餘的或時間敏感的),例如從各個提供商獲取鏡像相似數據的股票價格。

+0

感謝您的回覆。可以üplzz張貼完整的代碼,如何調用DoOperationsInParallelAsync()我們可以傳遞另一個函數名稱引用作爲回調。並從回調如何顯示例程時完成像「DoOperation1()完成」 – Thomas

+0

我添加了一個按鈕和標籤的例子。 – Romoku