2013-01-31 22 views
5

Tôi có Thư viện lớp di động (PCL) được nhắm mục tiêu tại Profile158 (Windows Store, .NET 4.5, Silverlight 5, Windows Phone 8). Tôi có thể dễ dàng làm việc với các phương thức trả về một loại Tác vụ và tất cả hoạt động như tôi mong đợi. Bất cứ khi nào tôi truy cập thuộc tính Result, nó kết thúc chạy mã không đồng bộ và trả về kết quả.Sử dụng Microsoft.bcl.async trong PCL với Mono Droid?

Tuy nhiên, nếu tôi sử dụng từ khóa async/await trong phương thức bên trong PCL, tôi sẽ nhận lại tác vụ. Tuy nhiên, khi tôi cố gắng truy cập thuộc tính Result, nó chặn và không bao giờ trả về.

Nhìn vào cửa sổ xuất debug trong Visual Studio trong cả hai trường hợp tôi thấy văn bản giống nhau:

Thread started: 
Thread started: 
Loaded assembly: Mono.Security.dll [External] 
Thread started: 
Thread started: 

Vì vậy, dường như nếu mã đang được chạy, nhưng nó không bao giờ quay trở lại thread UI. Có ai khác đã cố gắng sử dụng PCL với Microsoft.bcl.async trong PCL không?

Dự án Mono Droid của tôi được nhắm mục tiêu đến Android 2.1.

Cảm ơn, - John

Cập nhật:
Dưới đây là thêm một số thông tin về các kịch bản khác nhau. Thứ nhất, đây là mã mà không làm việc trên Mono Droid khi viết bằng mã UI:

var task = request.GetResponseAsync(); 
string html = task.Result.GetResponseText(); 

Sau đó tôi tạo các phương pháp sau đây trong PCL:

public async Task<string> Test() 
{ 
    IHttpResponse responce = await GetResponseAsync(); 
    return responce.GetResponseText(); 
} 

Và gọi nó với mã này từ mã UI mono:

string html = request.Test().Result; 

nó không bao giờ trở lại ...

+0

Nếu bạn sử dụng thuộc tính Kết quả, thuộc tính này sẽ bị chặn cho đến khi tác vụ hoàn tất. Nếu bạn đang làm điều đó từ cùng một chủ đề mà bản thân nhiệm vụ cần thực thi, về cơ bản bạn đã cho mình một bế tắc. Nó không phải là tất cả rõ ràng những gì mã của bạn hiện tại ... bạn có một chương trình ngắn nhưng đầy đủ chứng minh vấn đề? –

+0

@dsplaisted đã sử dụng lớp này với MonoDroid trong bản trình diễn của anh ấy tại BUILD - http://channel9.msdn.com/Events/Build/2012/3-004 - Tôi sẽ thêm thẻ PCL vào bài đăng này và đưa ra tín hiệu dơi - anh ta sẽ đi cùng trong giờ Redmond ... – Stuart

+0

Không liên quan đến câu hỏi của bạn, nhưng Microsoft.Bcl.Async vẫn là phiên bản beta. Sử dụng nó trong bất kỳ mã sản xuất nên tránh. Tất nhiên, bạn có thể chỉ đang thử nghiệm nó ngay bây giờ. –

Trả lời

3

Đây là một classic deadlock scenario, một tôi mô tả trên blog của mình.

Theo mặc định, await sẽ ghi lại "ngữ cảnh" và sử dụng nó để tiếp tục phương thức async. "Ngữ cảnh" này là SynchronizationContext hiện tại trừ khi nó là null, trong trường hợp đó là TaskScheduler hiện tại.

Vì vậy, bạn đang gọi phương thức async từ chuỗi giao diện người dùng (cung cấp số SynchronizationContext), sau đó chặn chuỗi giao diện người dùng bằng cách gọi Result. Phương pháp async không thể hoàn thành vì nó đang cố gắng hoàn tất trên chuỗi giao diện người dùng, bị chặn.

Để khắc phục điều này, hãy làm theo những hướng dẫn này:

  1. Sử dụng async tất cả các con đường xuống. Không gọi Result hoặc Wait trên Task s được trả về từ phương thức async; sử dụng await để thay thế.
  2. Sử dụng ConfigureAwait(false) bất cứ khi nào có thể trong mã thư viện của bạn.

Bạn cũng có thể tìm thấy async/await intro hữu ích của mình.

+0

Tôi đồng ý với việc chặn mã giao diện người dùng cho đến khi thao tác hoàn tất. Vấn đề là nó không bao giờ kết thúc và không bao giờ quay trở lại luồng UI. Nếu tôi trả lại một nhiệm vụ từ phương pháp của tôi và không sử dụng async/await, mã UI chặn một thời gian ngắn, và sau đó trả về. Tôi đã thử cùng một mã giao diện người dùng chính xác với Windows Phone 8 và ứng dụng Cửa hàng Windows và cả hai đều trả lại chính xác cho chuỗi giao diện người dùng. Tôi cũng đã kiểm tra để đảm bảo rằng SynchronizationContext không phải là null trong Android, và nó không phải là. Vì vậy, có một cái gì đó về Android và PCLs sử dụng async/chờ đợi mà dường như gây ra vấn đề. –

+0

Lỗi bế tắc này tồn tại trong tất cả các giao diện người dùng, bao gồm WP8 và netcore. Nếu bạn có mã sử dụng 'Kết quả' trên một phương thức' async' trong WP8 mà không có bế tắc và cùng một mã khóa * chính xác * trong Android, thì vui lòng đăng mã. –

+0

Tôi vừa đăng mã. –

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