c# – 从不同的线程调用时,WCF双工回调方法永远不会执行
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 从不同的线程调用时,WCF双工回调方法永远不会执行,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4216字,纯文字阅读大概需要7分钟。
内容图文
![c# – 从不同的线程调用时,WCF双工回调方法永远不会执行](/upload/InfoBanner/zyjiaocheng/788/edfd86dc854c4680abd227d42f1db4fb.jpg)
好的,我的机智已经结束了这件事.我有一个WCF双工服务.以下是架构的工作原理:
>客户端打开与端点的连接并提供回调实现
>该服务接受该请求并在其他线程上执行一些操作(可能是1秒可能是2分钟,这是我不使用异步操作的原因)
>处理完成后,它会调用客户端的回调
问题是当服务调用回调时,似乎没有任何反应.没有错误,没有任何东西.经过进一步调查,我在服务器跟踪中发现了一个异常:
The I/O operation has been aborted because of either a thread exit or an application request
这在尝试执行回调后立即发生.
客户端从未收到响应或关闭.发生的一切都是,因为初始请求是在与主要线程不同的线程上进行的,所以它只是永远等待那个线程完成.
最奇怪的是,如果我尝试在客户端调用的操作中调用回调,而不进入另一个线程,一切正常 – 回调被成功调用,这让我相信我已经正确配置了服务,但有线程/死锁问题.
以下是我如何调用该服务:
SubmissionServiceClient client = CreateClientInstance();
client.Open();
Guid executionId = await client.SubmitAsync(submission);
submissionCompletionSource.Task.Wait(); //waits for the callback to be called (I omitted the extra wiring code for better readability)
client.Close();
private SubmissionServiceClient CreateClientInstance()
{
NetHttpBinding binding = new NetHttpBinding();
binding.WebSocketSettings.TransportUsage = WebSocketTransportUsage.Always;
EndpointAddress endpointAddress = new EndpointAddress("ws://localhost:9080/SubmissionRouter");
InstanceContext instanceContext = new InstanceContext(this);
SubmissionServiceClient submissionServiceClient = new SubmissionServiceClient(instanceContext,binding,endpointAddress);
return submissionServiceClient;
}
这是回调操作:
public void SubmissionProcessed(SubmissionResultDto result)
{
submissionCompletionSource.TrySetResult(result);
}
这是客户端调用的服务操作:
public Guid Submit(SubmissionDto submission, ISubmissionCallback callback)
{
ExecutionDto execution = new ExecutionDto()
{
Id = Guid.NewGuid(),
Submission = submission
};
RequestExecution(execution); //Queues the execution of the operation
submissions.Add(execution.Id, callback);
return execution.Id;
}
这是服务调用客户端回调的地方(此方法在与初始请求的线程不同的线程上执行):
ISubmissionCallback callback = submissions[submissionResult.ExecutionId];
callback.SubmissionProcessed(submissionResult);
服务行为:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant)]
正如您在提交时看到的那样,该服务将回调存储在字典中,并与id配对,稍后它将用于检索回调并调用它.我相信失败的原因是因为我试图在另一个线程上做到这一点.
编辑:
我向服务添加了一个Ping操作,该操作调用另一个线程,该线程挂起3秒钟然后在客户端上调用Pong函数.
public void Ping()
{
var callback = OperationContext.Current.GetCallbackChannel<ISubmissionCallback>();
Task.Run(() =>
{
System.Threading.Thread.Sleep(3000);
callback.Pong();
});
}
客户:
课程
{
static void Main(string [] args)
{
NetHttpBinding binding = new NetHttpBinding();
binding.WebSocketSettings.TransportUsage = WebSocketTransportUsage.Always;
EndpointAddress endpointAddress = new EndpointAddress(“ws:// localhost:9080 / SubmissionRouter”);
InstanceContext instanceContext = new InstanceContext(new Callback());
SubmissionServiceClient submissionServiceClient = new SubmissionServiceClient(instanceContext,binding,endpointAddress);
submissionServiceClient.Ping();
Console.Read();
}
public void SubmissionProcessed(SubmissionResultDto result)
{
throw new NotImplementedException();
}
class Callback : ISubmissionServiceCallback
{
public void Pong()
{
Console.WriteLine("Pong!");
}
public void SubmissionProcessed(SubmissionResultDto result)
{
}
}
}
这实际上成功了.我设法在客户端收到我的答复.我现在正式完全迷失了.
解决方法:
如果您使用submissionCompletionSource.Task.Wait()阻止UI线程;这导致你的僵局.默认情况下,WCF回调在UI线程上发生,您可以使用CallbackBehaviorAttribute更改行为
[CallbackBehaviorAttribute(UseSynchronizationContext=false)]
class Callback : ISubmissionServiceCallback
{
public void Pong()
{
Console.WriteLine("Pong!");
}
public void SubmissionProcessed(SubmissionResultDto result)
{
}
}
或者不阻止UI线程.
SubmissionServiceClient client = CreateClientInstance();
client.Open();
Guid executionId = await client.SubmitAsync(submission);
await submissionCompletionSource.Task; //awaits for the callback to be called without blocking the UI.
client.Close();
内容总结
以上是互联网集市为您收集整理的c# – 从不同的线程调用时,WCF双工回调方法永远不会执行全部内容,希望文章能够帮你解决c# – 从不同的线程调用时,WCF双工回调方法永远不会执行所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。