让客户端成为System.Net.Http.HttpClient的一个实例。在以下代码中
var response = await client.PostAsync(url, content);
processResponse(response);在第一行代码和第二行代码之间没有线程块,所以如果我们在UI线程中,UI在后往返过程中保持响应。
获得相同的非阻塞行为的F#代码是什么?是
let response = client.PostAsync(url, content) |> Async.AwaitTask |> Async.RunSynchronously
processResponse(response)正确的密码?我还不清楚RunSynchronously是否阻塞了当前线程。如果是这样,我们如何获得与等待相同的非阻塞行为?
编辑
也许更多的背景会有帮助。
我有一个包含两个项目的Visual解决方案:一个WPF/WinForms应用程序和一个由应用程序引用的F#库。库提供一个名为FSLongWork()的函数/方法,它执行长I/O操作,例如使用HttpClient.GetAsync/PostAsync向远程服务器发送HTTP或POST,并返回一个字符串。应用程序前端是一个带有按钮和标签的简单窗口。按钮单击处理程序必须: 1)调用F#库中的F#();2)在标签中写入依赖于步骤1中返回的字符串的内容。当然,步骤1必须异步进行,以保持UI响应能力。
可能的C#应用解决方案
F#库:
let FSLongWork() =
async {
do! Async.Sleep(5000);
return "F#"
} |> Async.StartAsTaskC#应用程序单击处理程序
private async void button1_Click(object sender, EventArgs e) {
var s = await FSLongWork();
label1.Text = s;
}C#应用程序按钮处理程序注册
this.button1.Click += new System.EventHandler(this.button1_Click);可能的F#应用解决方案
F#库:
let FSLongWork() =
async {
do! Async.Sleep(5000);
return "F#"
}F#应用程序单击处理程序
let button1_Click (sender : obj) e =
async {
let! s = FSLongWork()
label1.Text <- s
}F#应用程序按钮处理程序注册
button1.Click.Add(RoutedEventHandler(fun sender e -> button1_Click sender e |> Async.StartImmediate)我看到的问题是,F#库函数(FSLongWork)在这两种解决方案中是不同的(|> Async.StartAsTask仅在第一种解决方案中),这在可重用性方面并不好。
我们可以使用F#中的第一个实现(将let! s = FSLongWork()更改为let! s = FSLongWork() |> Async.AwaitTask)。
第二个实现可以用于C# (将var s = await FSLongWork();更改为var s2 = await Microsoft.FSharp.Control.FSharpAsync.StartAsTask(FSLongWork(), null, null);)。
然而,在我看来,这有点尴尬:自然的F#实现将是第二个(没有Async.StartAsTask),但这需要引用Microsoft.FSharp和在C#应用程序中使用相当丑陋的Microsoft.FSharp.Control.FSharpAsync.StartAsTask(FSLongWork(), null, null);。
另一方面,第一个实现(使用Async.StartAsTask)导致了在C#中更自然的使用(简单地说是await FSLongWork()),但是当一个F#应用程序使用时,它意味着am异步->任务->异步往返。
是否有一种方法可以编写F#库,以便C#用户不需要引用FSharp.Core,并且不影响F#函数的实现方式?
发布于 2018-02-24 07:16:16
就良好的融合而言,我希望能够做到以下几点:
F#库:
let FSLongWork() =
async {
do! Async.Sleep(5000);
return "F#"
}C#应用程序单击处理程序
private async void button1_Click(object sender, EventArgs e) {
var s = await FSLongWork();
label1.Text = s;
}换句话说,当我在Async<>中使用await时,Task<>和C#之间的转换是自动的/隐式的。我认为这是可能的,我无法找到方法去做,因此我提出了问题。显然,这是不可能的,并且需要一些手动转换管道(例如,在我报告的可能的解决方案中)。
也许它可以作为未来功能请求的素材。
发布于 2018-02-23 09:25:33
所以在这种情况下:
async {
let! response = client.PostAsync(url, content) |> Async.AwaitTask
processResponse response
} |> Async.Starthttps://stackoverflow.com/questions/48944486
复制相似问题