2010-06-16 24 views
10

Tôi đang cố gắng tạo một cuộc gọi Rpc cho máy chủ web JBOSS từ Silverlight (4). Tôi đã viết mã và nó đang làm việc trong một ứng dụng giao diện điều khiển - vì vậy tôi biết rằng Jboss đang đáp ứng yêu cầu web. vấn đề porting nó để Silverlight 4, đang gây ra:Silverlight HttpWebRequest.Create treo bên trong khối async

let uri = new Uri(queryUrl) 
// this is the line that hangs 
let request : HttpWebRequest = downcast WebRequest.Create(uri) 
request.Method <- httpMethod; 
request.ContentType <- contentType 

Nó có thể là một vấn đề sandbox, như Silverlight của tôi đang được phục vụ tắt của hệ thống tập tin của tôi và Uri là một tham chiếu đến localhost - mặc dù tôi thậm chí không nhận được một ngoại lệ. Suy nghĩ?

Thx


UPDATE 1

Tôi tạo ra một dự án mới và chuyển mã của tôi hơn và bây giờ nó đang làm việc; một cái gì đó phải không ổn định w/liên quan đến việc tích hợp Silverlight F # vẫn còn. Vẫn sẽ đánh giá cao suy nghĩ về gỡ lỗi các "treo" web tạo trong mô hình cũ ...


CẬP NHẬT 2

let uri = Uri("http://localhost./portal/main?isSecure=IbongAdarnaNiFranciscoBalagtas") 
// this WebRequest.Create works fine 
let req : HttpWebRequest = downcast WebRequest.Create(uri) 

let Login = async { 
    let uri = new Uri("http://localhost/portal/main?isSecure=IbongAdarnaNiFranciscoBalagtas") 
    // code hangs on this WebRequest.Create 
    let request : HttpWebRequest = downcast WebRequest.Create(uri) 
    return request 
} 
Login |> Async.RunSynchronously 

tôi phải mất một cái gì đó; khối Async hoạt động tốt trong ứng dụng bảng điều khiển - là nó không được phép trong ứng dụng Silverlight?

+0

Có một bản cập nhật về vấn đề này - bạn đã có được nó để làm việc ... – akaphenom

Trả lời

5

(Cảm ơn để gửi này để fsbugs, để buộc chúng ta phải có một cái nhìn cứng.)

vấn đề là Async.RunSynchronously. Khi được gọi trên chuỗi giao diện người dùng, thao tác này sẽ chặn chuỗi giao diện người dùng. Và nó chỉ ra rằng WebRequest.Create() trên Silverlight gửi đến thread UI. Vì vậy, nó là một bế tắc.

Nói chung, hãy cố gắng tránh Async.RunSynchronously trên Silverlight (hoặc trên bất kỳ chuỗi giao diện người dùng nào). Bạn có thể sử dụng Async.StartImmediate trong ví dụ này. Ngoài ra, tôi nghĩ bạn có thể gọi RunSynchronously từ bất kỳ chủ đề nền nào mà không gặp sự cố. (Tôi đã không cố gắng đủ end-to-end kịch bản Silverlight bản thân mình để cung cấp thêm những lời khuyên như được nêu ra. Bạn có thể kiểm tra

Game programming in F# (with Silverlight and WPF)

F# and Silverlight

F# async on the client side

cho một vài ví dụ ngắn.)

(Nhìn lại, nhóm thiết kế F # nghĩ rằng chúng tôi có lẽ không nên bao gồm Async.RunSynchronously trong FSharp.Core cho Silverlight; ly vi phạm tinh thần của nền tảng (không có cuộc gọi chặn). Có thể chúng tôi sẽ ngừng sử dụng phương thức đó trong các bản phát hành Silverlight trong tương lai. Mặt khác, nó vẫn có các ứng dụng hợp lệ cho sự tương đương song song với CPU trên Silverlight, ví dụ: chạy một bó trên (non-IO) mã song song trên các chủ đề nền.)

0

Tôi gặp sự cố tương tự. Tôi đã tạo một ViewModel Silverlight MVVM để liên kết dữ liệu từ web. Don Syme nhận xét bản thân:

Tôi không phải là một chuyên gia về dữ liệu ràng buộc, nhưng tôi tin rằng bạn không thể “ẩn” các asyncness của một mô hình quan điểm như thế này cho WPF và Silverlight . Tôi nghĩ bạn cần phải hiển thị Task, Async hoặc bộ sưu tập quan sát được. AFAIK chỉ cách để nhận Silverlight và WPF để ràng buộc không đồng bộ với thuộc tính là nếu nó là một bộ sưu tập quan sát được.

Dù sao, tôi đã cài đặt F # Power Pack để nhận AsyncReadToEnd. Nó không giải quyết được trường hợp ... Tôi đã thêm tên miền vào các trang tin cậy nhưng nó không giúp được gì ... Sau đó, tôi đã thêm một tệp MySolution.Web -asp.net-site và clientaccesspolicy.xml. Tôi không biết liệu chúng có ảnh hưởng gì không.

Bây giờ, với Async.StartImmediate tôi có web gọi dịch vụ làm việc:

let mutable callresult = "" 
//let event = new Event<string>() 
//let eventvalue = event.Publish 
let internal fetch (url : Uri) trigger = 
    let req = WebRequest.CreateHttp url 
    //req.CookieContainer <- new CookieContainer() 
    let asynccall = 
     async{ 
      try 
       let! res = req.AsyncGetResponse() 
       use stream = res.GetResponseStream() 
       use reader = new StreamReader(stream) 
       let! txt = reader.AsyncReadToEnd() 
       //event.Trigger(txt) 
       callresult <- txt //I had some processing here... 
       trigger "" |> ignore 
      with 
       | :? System.Exception as ex -> 
        failwith(ex.ToString()) //just for debug 
     } 
    asynccall |> Async.StartImmediate 

Bây giờ tôi sẽ cần ViewModel của tôi để lắng nghe các callresult thể thay đổi. Trong trường hợp của bạn, bạn cũng cần một crossdomain.xml đến máy chủ.

Trigger là cần thiết để sử dụng giao diện người dùng sợi:

let trigger _ = 
    let update _ = x.myViewModelProperty <- callresult 
    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(new Action(update)) |> ignore 
fetch serviceUrl trigger 
Các vấn đề liên quan