Silverlight HttpWebRequest.Create在异步块内挂起

时间:2010-06-16 15:17:18

标签: silverlight f# silverlight-4.0 httpwebrequest asynchronous

我正在尝试从Silverlight(4)将Rpc调用原型化为JBOSS网络服务器。我编写了代码,它正在一个控制台应用程序中工作 - 所以我知道Jboss正在响应Web请求。将它移植到silverlight 4会导致问题:

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

这可能是一个沙盒问题,因为我的Silverlight是从我的文件系统提供的,而Uri是对本地主机的引用 - 尽管我甚至没有得到例外。想法?

THX


更新1

我创建了一个新项目并移植了我的代码,现在它正在工作;关于F#Silverlight集成的东西必须是不稳定的。仍然会欣赏有关在旧模型中调试“悬挂”网页创建的想法...


更新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
我必须遗漏一些东西; Async块在控制台应用程序中运行良好 - Silverlight应用程序中是否允许它?

4 个答案:

答案 0 :(得分:5)

(感谢您将此信息发送给fsbugs,强迫我们仔细查看。)

问题是Async.RunSynchronously。在UI线程上调用时,这将阻止UI线程。事实证明,Silverlight上的WebRequest.Create()会调度到UI线程。所以这是一个僵局。

通常,尽量避免在Silverlight(或任何UI线程)上使用Async.RunSynchronously。您可以在此示例中使用Async.StartImmediate。或者,我认为您可以从任何后台线程中调用RunSynchronously而不会出现问题。 (我还没有尝试过足够的端到端Silverlight场景来提供更多建议。你可以查看

Game programming in F# (with Silverlight and WPF)

F# and Silverlight

F# async on the client side

举几个简短的例子。)

(回想起来,F#设计团队认为我们可能不应该在FSharp.Core中包含Async.RunSynchronously用于Silverlight;该方法可能违反平台的精神(没有阻塞调用)。我们可能' ll在将来的Silverlight版本中不赞成使用该方法。另一方面,它仍然可以在Silverlight上实现CPU密集型并行性的有效用途,例如在后台线程上并行运行(非IO)代码。)

答案 1 :(得分:2)

这里看起来像一个类似的问题 - 虽然没有引用silverlight(实际上它是一个“Windows服务类”):

http://social.msdn.microsoft.com/Forums/en-US/netfxnetcom/thread/10854fc4-2149-41e2-b315-c533586bb65d

答案 2 :(得分:0)

我有类似的问题。我正在制作一个Silverlight MVVM ViewModel来绑定来自web的数据。 Don Syme评论道:

  

我不是数据绑定专家,但我   相信你不能“隐藏”异步性   对于WPF和WPF这样的视图模型   Silverlight的。我想你需要   公开任务,异步或   可观察的集合。 AFAIK唯一   让Silverlight和WPF绑定的方法   与属性异步的是它   是一个可观察的集合。

无论如何,我安装了F#Power Pack来获取AsyncReadToEnd。 它没有解决这个问题...我将域名添加到可信站点,但它没有帮助...然后我添加了一个MySolution.Web -asp.net-site和clientaccesspolicy.xml。我不知道那些是否有任何影响。

现在,使用Async.StartImmediate我得到了Web服务调用:

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

现在我需要我的ViewModel来监听可变的callresult。 在您的情况下,您还需要一个服务器的crossdomain.xml。

使用UI线程需要触发器:

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

答案 3 :(得分:-1)