简短版本:
如何创建在回调触发器上完成的Promise<Result>
?
长版:
我正在开发一个处理第三方SOAP服务的应用程序。来自用户的请求同时委托多个SOAP服务,聚合结果并发送回用户。
系统需要可扩展,并且应该允许多个并发用户。当每个用户请求最终触发大约10个Web服务调用并且每个呼叫阻塞大约1秒时,系统需要设计为具有非阻塞I / O.
我在Play Framework(Java)中使用Apache CXF来实现此系统。我已设法生成异步WS客户端代理并启用异步传输。我无法弄清楚当我委托给多个Web服务代理时如何返回Future to Play的线程,结果将作为回调获得。
选项1:使用返回Java Future的异步方法调用。
如此scala.concurrent.Future wrapper for java.util.concurrent.Future主题中所述,我们无法将Java Future转换为Scala Future。从Future获得结果的唯一方法是执行阻止调用者的Future.get()
。由于CXF生成的代理返回Java Future,因此排除了此选项。
选项2:使用Scala Future。
由于CXF生成代理接口,我不确定是否有任何方法可以干预并返回Scala Future(AFAIK Akka使用Scala Futures)而不是Java Future?
选项3:使用回调方法。
CXF生成的返回Java Future的异步方法也需要一个回调对象,我想这会在结果准备就绪时提供回调。要使用这种方法,我需要返回一个等待我收到回调的Future。
我认为选项3 是最有希望的,虽然我对如何返回将在收到回调时完成的Promise没有任何想法。我可能有一个线程在while(true)
等待并等待,直到结果可用。同样,我不知道如何在不阻塞线程的情况下进入wait
?
简而言之,我正在尝试构建一个正在进行大量SOAP Web服务调用的系统,其中每个调用都会占用大量时间。在许多并发Web服务调用的情况下,系统可能很容易耗尽线程。我正在努力寻找一种基于非阻塞I / O的解决方案,它可以同时允许许多正在进行的Web服务调用。
答案 0 :(得分:2)
选项3看起来不错:)开始使用几个进口......
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace wmic_forms
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public string x;
private void button1_Click(object sender, EventArgs e)
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "C:\\ken.bat";
Process p = Process.Start(psi);
string strOutput = p.StandardOutput.ReadToEnd();
//p.WaitForExit();
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.Arguments = textBox1.Text;
MessageBox.Show(strOutput);
//Console.WriteLine(strOutput);
//Console.ReadLine();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
//my input text box for IP
x = textBox1.Text;
}
}
}
并且,为了说明这一点,这里是一个采用回调的模拟CXF API:
import scala.concurrent.{Await, Promise}
import scala.concurrent.duration.Duration
创建一个promise,使用promise作为回调调用API:
def fetch(url: String, callback: String => Unit) = {
callback(s"results for $url")
}
然后,您可以将val promise = Promise[String]
fetch("http://corp/api", result => promise.success(result))
promise.future
的实例带入您的Play应用。
要测试它,你可以这样做:
Future
将阻止等待结果,此时您应该在控制台中看到“http://corp/api的结果”。