尝试将消息推送到 UI 并接收一些结果以从 Web 服务同步返回。 方法代码如下。
[OperationContract]
public string DecypherCaptcha(string captcha)
{
var connection = new HubConnection("http://localhost:51806");
IHubProxy hub = connection.CreateHubProxy("robo");
string decaptcha = null;
hub.On("captchaDecyphered", decyphered =>
{
decaptcha = decyphered;
});
connection.Start().Wait();
hub.Invoke<string>("DecypherCaptcha", new object[] { captcha });
return decaptcha;
}
问题是该方法在从集线器的 captchaDecyphered
获取值之前完成。然而表达式 { decaptcha = decyphered; }
在方法退出后从服务器正常触发。
添加 ManualResetEvent
标志和 WaitOne()
并不能解决卡住执行并阻止 hub.On("captchaDecyphered"
触发的问题。
有什么想法如何同步吗?
UPDATE#1 小通知。 无法避免使用中间同步 WCF Web 服务作为 SignalR 客户端,因为后面有非常特定的机器人,它们能够与外部交互world 只能通过同步调用 webservices 来实现。基本上在这种情况下,当机器人面对验证码时,它会调用 Web 服务,通过 SignalR 将其传递到 UI 以进行手动识别。
UPDATE#2 感谢 @Ken 的鼓舞人心的建议,通过将连接建立和集线器方法调用封装到单独的“线程”中,然后等待“ManualResetEvent”来使其工作:
new Thread(() =>
{
connection.Start().Wait();
hub.Invoke<string>("DecypherCaptcha", new object[] { captcha });
}).Start();
sync.WaitOne();
之前曾尝试从“任务”开始,假设它会隐式在单独的线程上运行,但没有成功。
最佳答案
您可以拥有 DecypherCaptcha
SignalR 服务器上的 hub 方法将解密的验证码返回为 Task<string>
而不是调用 captchaDecyphered
.
您可能想使用TaskCompletionSource帮助您创建适当的任务。基本上你可以打电话 tcs.SetResult(deciphered)
并返回tcs.Task
而不是打电话 Clients.Caller.captchaDecyphered(deciphered)
.
那么您的客户端代码将简单地是:
[OperationContract]
public string DecypherCaptcha(string captcha)
{
var connection = new HubConnection("http://localhost:51806");
IHubProxy hub = connection.CreateHubProxy("robo");
connection.Start().Wait();
return hub.Invoke<string>("DecypherCaptcha", captcha).Result;
}
关于multithreading - SignalR 等待结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14587243/