none
非同步下載資料問題 (async/await) RRS feed

  • 一般討論

  • private async void button1_Click(object sender, EventArgs e)
            {
                MessageBox.Show("main: " + Thread.CurrentThread.ManagedThreadId.ToString());
             
                await DownloadAsync();
                
                // do other tasks
            }
    
    public async Task DownloadAsync()
            {
                MessageBox.Show("sii inner: " + Thread.CurrentThread.ManagedThreadId.ToString());
               
                using (HttpClient httpClient = new HttpClient())
                {
                    httpClient.Timeout = TimeSpan.FromSeconds(10);
    
                    foreach (var url in urlList)
                    {
                        var stream = httpClient.GetStreamAsync(url);
                        HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
                        doc.Load(await stream);
                        var row = doc.DocumentNode.SelectSingleNode("body[1]/table[2]").ChildNodes[0];
    
                        while (row != null)
                        {
                            MatchHandler(ref row); //這是另一個委派方法,省略
                        }   
    
                    }
                }
                
            }

    我希望DownloadAsync的部分能用非同步方法去做,並且往後能實作取消以及等待完成等等功能

    (因此不考慮使用ThreadPool或backgroundworker)

    但我使用了Thread.CurrentThread.ManagedThreadId 去測試當前執行緒,在await前 以及 await後都是同一隻執行緒。

    碰到await關鍵字不是應該立即返還嗎?

    我已經爬了一些高手的部落格(Huan-Lin學習筆記, 黑暗執行緒等),還是不曉得問題癥結點,是否有前輩能點出我的盲點?


    2016年7月24日 上午 10:14

所有回覆

  • 你用了 await, 就表示那邊會有個 wait handle 等待 DownloadAsync() 完成才會往下.

    你把 "await" 拿掉, 他就不會等了. (雖然會有編譯器警告).

    或者, 你可宣告成 public async void DownloadAsync(), 這樣就沒辦法 await 了

    之前有篇關於這問題的討論

    https://social.msdn.microsoft.com/Forums/zh-TW/f851634f-b617-492c-a3c7-a0b1121ab9e0/asyncawait-?forum=233


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    2016年7月24日 上午 11:53
    版主
  • 謝謝回答,我懂你的意思,但我的問題是:

    我希望我的UI不要鎖死,我在跑DownloadAsync這一段的時候,我的執行緒是UI執行緒,導致我的UI鎖死,我在不考慮使用ThreadPool或backgroundworker的情況下,該怎麼達成我的目的呢?

    2016年7月24日 下午 12:15
  • 用 Task.Run 包起來 (我用 WPF 試的)

      public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
          private void Button_Click(object sender, RoutedEventArgs e)
            {
                DoSomething();
                txt.Text = "111";
            }
    
            async private void DoSomething()
            {
                HttpClient clinet = new HttpClient();
                await clinet.GetStringAsync("http://yahoo.com.tw");
                await Task.Run(() => Thread.Sleep(10000));
                txt.Text = "999";
            }
        }

    
    


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。



    2016年7月24日 下午 02:42
    版主
  • 謝謝回答,我其實也有考慮過Task以及Thread<o:p></o:p>

    但下面這篇文章說,Task這樣寫是"假的"非同步方法,我實在不是很懂他為什麼會說是假的?<o:p></o:p>

    huan-lin.blogspot.com/2016/01/dont-write-fake-async-methods.html
    (抱歉,帳號認證問題待解決,沒辦法貼超連結)

    • 已編輯 蘭克 2016年7月25日 上午 11:51
    2016年7月25日 上午 11:51
  • 因為你排除了很多東西, 一開始不用 ThreadPool, 不用 BackgroundWorker , 所以我猜你可能會喜歡用 Task.Run()

    那既然你對 Task.Run 也不想用.

    那大概剩下兩個選擇

    (1) 用 Thread 自己搞, 這個看 Thread  類別應該就行了

    (2) 實作 Task Based Async Pattern

    Implementing the Task-based Asynchronous Pattern

    順便以下的內容也要看

    https://msdn.microsoft.com/zh-tw/library/system.iasyncresult(v=vs.110).aspx

    https://msdn.microsoft.com/en-us/library/ms228975(v=vs.110).aspx


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    2016年7月25日 下午 03:40
    版主
  • 我並沒有說我不想用Task.Run()呀, 而且我目前的問題確實是使用Task.Factory.StartNew以及Task.WhenAll解決的,和您回覆給我的寫法很相似 (我原本是使用async/await 但是卻遇到如上問題)。 

    因此我發這篇討論文主要的目的如下:
    1. 在我發文前我就已經解決了我的問題(利用Task.Factory.StartNew以及Task.WhenAll) 但我還是不清楚為什麼我原本的方式(async/await)會錯,我認為我應該要弄清楚這個問題,所以才來討論版上發問

    2. 我後來爬文看到 http://huan-lin.blogspot.com/2016/01/dont-write-fake-async-methods.html 這篇文章說大量用Task.Run可能會導致執行緒集區耗盡的問題,雖然我還沒遇到,但往後我會越開越多工作執行緒去非同步下載資料,我也還是希望能盡量避免問題發生,因此想在版上知道其他前輩會利用怎麼樣的方式解決這個問題

    希望您別誤會,也謝謝您提供方向讓我參考!!

    2016年7月28日 上午 04:05