2010-06-16 15 views
10

Próbuję prototypować wywołanie Rpc do serwera WWW JBOSS z Silverlight (4). Napisałem kod i działa on w aplikacji konsolowej - więc wiem, że Jboss odpowiada na żądanie sieci. Porting go do Silverlight 4, jest przyczyną problemów:Silverlight HttpWebRequest.Create zawiesza się wewnątrz bloku asyncowego

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

może to być problem piaskownicy, jak mój Silverlight jest podawane z mojego systemu plików i Uri jest odniesienie do localhost - chociaż nie jestem nawet uzyskanie wyjątku. Myśli?

Thx


UPDATE 1

stworzyłem nowy projekt i przeniesiony na mój kod, a teraz pracuje; coś musi być niestabilne w odniesieniu do integracji F # Silverlight. Nadal będzie wdzięczna przemyślenia na temat debugowania "wisi" web stworzyć w starym modelu ...


UPDATE 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 

I musi być brakuje czegoś; blok Async działa dobrze w aplikacji konsoli - czy nie jest to dozwolone w aplikacji Silverlight?

+0

czy jest to aktualizacja - to masz do pracy ... – akaphenom

Odpowiedz

5

(Dzięki za wysłanie tego do fsbugs, aby zmusić nas do podjęcia twarde spojrzenie.)

problemem jest Async.RunSynchronously. Po wywołaniu w wątku UI blokuje to wątek interfejsu użytkownika. I okazuje się, że WebRequest.Create() na Silverlight wysyła do wątku UI. To jest impas.

Ogólnie, staraj się unikać Async.RunSynchronously na Silverlight (lub w dowolnym wątku UI). W tym przykładzie można użyć Async.StartImmediate. Alternatywnie, myślę, że możesz zadzwonić pod numer RunSynchronously z dowolnego wątku w tle bez problemów. (Nie próbowałem wystarczająco end-to-end Silverlight scenariusze się zaoferować więcej porad jak dotychczas. Możecie sprawdzić

Game programming in F# (with Silverlight and WPF)

F# and Silverlight

F# async on the client side

na kilka krótkich przykładów.)

(Z perspektywy czasu zespół projektantów F # uważa, że ​​być może nie powinniśmy dołączyć Async.RunSynchronously w FSharp.Core dla Silverlight; ly narusza ducha platformy (bez blokowania połączeń). Możliwe, że wycofamy tę metodę w przyszłych wersjach Silverlight. Z drugiej strony, wciąż ma on ważne zastosowania dla paralelizmu intensywnego CPU na Silverlight, np. uruchamianie równoległego kodu (non-IO) na wątkach w tle.)

0

Miałem podobny problem. Robiłem SilverVight MVVM ViewModel do wiązania danych z sieci. Don Syme skomentował siebie:

Nie jestem ekspertem wiązania danych, ale wierzę, nie można „ukryć” THE asyncness modelu widok jak ten dla WPF i Silverlight . Wydaje mi się, że musiałbyś ujawnić zadanie, Async lub kolekcję obserwowalną . AFAIK to jedyny sposób, aby uzyskać Silverlight i WPF do wiązania asynchronicznie z właściwością , jeśli to jest kolekcją obserwowalną.

W każdym razie zainstalowałem F # Power Pack, aby pobrać AsyncReadToEnd. To nie rozwiązało sprawy ... Dodałem domeny do zaufanych stron, ale to nie pomogło ... Potem dodałem stronę MySolution.Web -asp.net i clientaccesspolicy.xml. Nie wiem, czy to miało jakiś wpływ.

Teraz z Async.StartImmediate mam pracując rozmowę usługę:

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 

Teraz będę potrzebował mojego ViewModel aby słuchać zmienny callresult. W twoim przypadku potrzebujesz również pliku crossdomain.xml na serwerze.

Spust jest potrzebne do korzystania z UI-wątek:

let trigger _ = 
    let update _ = x.myViewModelProperty <- callresult 
    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(new Action(update)) |> ignore 
fetch serviceUrl trigger 
Powiązane problemy