C# 有没有一种简单的方法来模拟WCF服务和WCF客户端之间的事件?

C# 有没有一种简单的方法来模拟WCF服务和WCF客户端之间的事件?,c#,wcf,events,callback,ipc,C#,Wcf,Events,Callback,Ipc,因此,我实现了客户端EXE和服务器EXE之间的localhost WCF命名管道通信。我可以通过localhost在服务器上调用类方法。所以,它就像一个IPC/RPC。但是,如果服务器的类方法需要很长时间才能执行,那么我最好将其放入线程中,以便服务器类方法在后台完成并运行该线程。好的,好的,但是当线程完成它的长任务时,我想提醒客户机,而不必在客户机上使用计时器来检查该类方法。计时器命中类方法比引发的事件效率低得多。就像我需要从服务器在客户端引发事件一样。有没有一种简单的方法可以做到这一点,或者至

因此,我实现了客户端EXE和服务器EXE之间的localhost WCF命名管道通信。我可以通过localhost在服务器上调用类方法。所以,它就像一个IPC/RPC。但是,如果服务器的类方法需要很长时间才能执行,那么我最好将其放入线程中,以便服务器类方法在后台完成并运行该线程。好的,好的,但是当线程完成它的长任务时,我想提醒客户机,而不必在客户机上使用计时器来检查该类方法。计时器命中类方法比引发的事件效率低得多。就像我需要从服务器在客户端引发事件一样。有没有一种简单的方法可以做到这一点,或者至少可以模拟它,而不需要做大量令人困惑的工作?

因此,假设您在UI中单击一个按钮,对WCF服务执行WCF同步方法调用,并且该同步方法需要很长时间才能运行。显然,您不希望在执行长时间运行的任务时阻止UI更新。当然,您可能会考虑回调。与中一样,您对服务器进行调用,服务器上的class方法生成一个线程并运行该任务,完成后,它通过回调将结果返回给客户端

事实上,在WCF上建立这一切涉及到许多复杂、混乱、缺乏文档记录的步骤。但是有一种更简单的方法,它根本不涉及WCF代码,也不涉及您在WCF服务上更改任何内容,也不涉及编辑任何WCF配置。NET4.5及更高版本中引入了这一技巧。它被称为
async
wait
。下面是一个按钮单击的示例,它调用一个WCF服务方法,该方法需要很长时间才能运行,完成后返回结果,但GUI不会锁定,并且可以处理其他事件

一,。首先,要模拟慢速任务,请编辑WCF服务项目的共享类方法,并在返回结果之前添加此行,以便可以模拟5秒的暂停:

Thread.Sleep(5000); // requires using System.Threading;
在我的例子中,我把它放在我的
GetData()
方法中

二,。现在切换到您的WCF客户端项目。您可能有一个按钮单击处理程序,如下所示,例如:

private void button1_Click(object sender, EventArgs e)
{
  string returnString = client.GetData(textBox1.Text));
  label1.Text = returnString;
}
因此,通过三个小的改变来切换:

a。使用System.Threading.Tasks添加

b。在按钮单击处理程序上,将
private void…
更改为
private async void…

c。利用
等待任务。使用慢速方法调用运行(…)

因此,代码看起来是这样的:

private async void button1_Click(object sender, EventArgs e)
{
  // Task.Run() requires "using System.Threading.Tasks;"
  string returnString = await Task.Run(() => client.GetData(textBox1.Text));
  label1.Text = returnString;
}
最终结果是,当您单击WCF客户端项目中的按钮时,会在后台线程中对WCF服务项目调用GetData()类方法,完成后,它返回到
wait
语句,并将结果返回给变量赋值。在我的例子中,我点击了按钮,5秒钟内什么也没发生——带有结果字符串的标签没有改变。然而,GUI并没有被锁定——我可以拖动窗口,输入其他字段,单击其他表单按钮,等等。所以,它几乎像一个回调事件处理程序,但不完全是这样。尽管如此,它仍然提供相同的功能,并且在大多数情况下可以用来代替回调事件处理程序。而且它涉及的代码要少得多。


这是根据我对OP问题的评论得出的答案



您可以使用您的WCF方法,然后只需执行
async/await
,或者完全取消WCF,并使用内置的async和
NamedPipeClientStream
(它仍然与await兼容)。更不用说后者在消除冗长的XML SOAP编码时的速度提升了

作品:


@MickyD您在异步/等待方面是对的,现在我已经研究了它并实现了一个有效的测试。这使我几乎可以在长时间运行的任务上模拟回调,并且只需要最少的代码行

e、 g.以OP的答案为基础,但正确使用
async/await

客户端代码
您可以使用您的WCF方法,然后只需执行
async/await
,或者完全取消WCF,并使用内置的async和
NamedPipeClientStream
(它仍然与
await
兼容)。更不用说后者在消除冗长的XML SOAP时的速度提升了encoding@MickyD现在我已经研究了异步/等待,并实现了一个有效的测试,您在这方面是正确的。这让我几乎可以用最少的代码行模拟长时间运行的任务上的回调。为什么我不必在WCF服务EXE中实现
task async GetDataAsync(string test)
?看起来Microsoft会自动为您创建
*async(*)
类方法。我创建了一个
Example2()
,然后在客户端上进行了更新服务引用,然后能够自动调用
Example2Async()
。@Volomike是的。您可能想看一看,因为它可以防止客户端代理与实际服务不一致的问题。:)
private async void button1_Click(object sender, EventArgs e) // <-- note async
{
    label1.Text = await client.GetDataAsync(textBox1.Text); // <-- note await. New method
}
Task<string> async GetDataAsync (string text)
{
    await Task.Delay (Timespan.FromSeconds(5));
    return text + " processed";
}