2014-05-16 21 views
5

Tôi đang cố gắng thiết kế một trình duyệt sẽ tìm nạp các cập nhật trang web theo chương trình. Tôi đang cố gắng để làm điều này với các phương pháp async/await nhưng khi tôi cố gắng và chạy chương trình có vẻ như chỉ treo trên response.Wait() ;. không chắc chắn tại sao hoặc những gì đang xảy ra.hoạt động async httpclient

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     var urls = sourceUrls(); 
     Task<HttpResponseMessage> response = login(urls[0]); 
     response.Wait(); 

     Console.Write("Complete"); 

    } 

    private List<Site> sourceUrls() 
    { 

     var urls = new List<Site>(); 
     urls.Add(new Site("http://yahoo.com", "test", "test")); 

     return urls; 
    } 
} 

lớp trình duyệt ::

static public class Browser 
{ 

    private static CookieContainer cc = new CookieContainer(); 
    private static HttpClientHandler handler = new HttpClientHandler(); 
    public static HttpClient browser = new HttpClient(handler); 

    static Browser() 
    { 
     handler.CookieContainer = cc; 
    } 


    static public async Task<HttpResponseMessage> login(Site site) 
    { 
     var _postData = new Dictionary<string, string> 
     { 
      {"test", "test"} 
     }; 

     FormUrlEncodedContent postData = new FormUrlEncodedContent(_postData); 
     HttpResponseMessage response = await browser.PostAsync(site.url, postData); 
     return response; 
    } 
} 

Ngoài ra, với mục đích dự định của tôi, là nó ok để làm cho trình duyệt một hàm tĩnh, hoặc Điều đó không có ý nghĩa? Xin lỗi cho các câu hỏi, mới đến C#

+0

nó sẽ cho phép bạn thực hiện 'MainWindow()' một phương thức 'async'? Nếu bạn có thể thì bạn chỉ có thể chờ đợi thay thế. Tôi khá chắc chắn rằng 'Task.Wait()' là một phương pháp chặn. – pquest

+0

tôi đã được ấn tượng rằng mainwindow() là chính() tương đương trong WPF, do đó, nó là một phương pháp chặn dự kiến. – cubesnyc

+0

Tôi đã chỉnh sửa tiêu đề của bạn. Vui lòng xem, "[Câu hỏi có bao gồm" thẻ "trong tiêu đề của chúng không?] (Http://meta.stackoverflow.com/questions/19190/)", trong đó sự đồng thuận là "không, chúng không nên". –

Trả lời

1

Đó là một ý tưởng tồi để gọi Wait trên Task trong một thread UI, nó kết quả trong một bế tắc. Bạn có thể chỉ cần await câu trả lời sẽ đạt được những gì bạn muốn. Các await unwraps phản ứng từ Task để loại trở lại của bạn bây giờ chỉ là HttpResponseMessage. Bởi vì bạn không thể đánh dấu các hàm tạo là async, bạn có thể di chuyển chức năng này sang một phương thức khác bắt đầu hoạt động.

public MainWindow() 
{ 
    InitializeComponent(); 
    LoadUrlsAsync(); 
} 

public async Task LoadUrlsAsync() 
{ 
    var urls = sourceUrls(); 
    HttpResponseMessage response = await login(urls[0]); 

    Console.Write("Complete"); 
} 

Xem this bài viết để có các phương pháp hay nhất khi sử dụng async/await.

Hoặc bạn có thể sử dụng phương pháp mở rộng Task.ConfigureAwait để định cấu hình tiếp tục không chạy trên SyncrhronizationContext hiện tại cũng nên tránh bế tắc.

public MainWindow() 
{ 
    InitializeComponent(); 

    var urls = sourceUrls(); 
    Task<HttpResponseMessage> response = login(urls[0]).ConfigureAwait(false); 
    response.Wait(); 

    Console.Write("Complete"); 
} 
+1

Mainwindow không thể được khai báo là không đồng bộ, và vì vậy ví dụ đầu tiên của bạn sẽ không hoạt động. – cubesnyc

+0

cảm ơn, đã được khắc phục ngay bây giờ. –

0

Cả hai GetUrl()GetUrl2(), bên dưới, hoàn thành những gì bạn đang tìm kiếm theo những cách hơi khác nhau. Tuy nhiên, hãy lưu ý rằng Task.Wait sẽ chặn luồng hiện tại (trong trường hợp này là chuỗi giao diện người dùng) cho đến khi tác vụ hoàn tất. Tôi đoán đây không phải là những gì bạn muốn làm.

using System.Diagnostics; 
using System.Net.Http; 
using System.Threading.Tasks; 
using System.Windows; 

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     GetUrls(); 
     GetUrls2(); 
    } 
    private void GetUrls() 
    { 
     var response = Task.Run(() => Browser.login("http://yahoo.com")); 
     response.Wait(); 
     Debug.WriteLine("Complete GetUrls()"); 
    } 
    private void GetUrls2() 
    { 
     var browseTask = Browser.login("http://yahoo.com"); 
     browseTask.ContinueWith((r) => Debug.WriteLine("Complete GetUrls2()")); 
    } 
} 
static public class Browser 
{ 
    static public async Task<HttpResponseMessage> login(string site) 
    { 
     var browser = new HttpClient(); 
     return await browser.GetAsync(site); 
    } 
} 
1

Wait gây ra a deadlock that I explain in full on my blog. Giải pháp tốt nhất là sử dụng await như đã đề xuất.

Trong trường hợp của bạn, các nhà xây dựng không thể là async, vì vậy điều đó là không thể. Điều này nên là một dấu hiệu cho thấy những gì bạn đang cố gắng làm có thể không phải là điều tốt nhất để làm. Cụ thể, bạn đang cố gắng chặn luồng giao diện người dùng chờ đợi quá trình tải xuống hoàn tất; điều này gần như không bao giờ là một ý tưởng hay. Thay vào đó, hãy khởi tạo hoạt động không đồng bộ và (đồng bộ) tải chế độ xem không hiển thị dữ liệu Sau đó, khi hoạt động không đồng bộ hoàn tất, nó sẽ cập nhật chế độ xem với dữ liệu mới. Tôi có một bài viết trên async data binding khám phá một kỹ thuật có thể.

Các vấn đề liên quan