1

基本上正如问题所述,如果我使我的服务异步,这是否意味着它们不再可互操作?

4

3 回答 3

2

就客户端而言,服务的同步或异步版本是相同的(参见下面的示例)。因此同步/异步决策不会影响互操作性。

public class StackOverflow_6231864_751090
{
    [ServiceContract(Name = "ITest")]
    public interface ITest
    {
        [OperationContract]
        string Echo(string text);
        [OperationContract]
        int Add(int x, int y);
    }
    [ServiceContract(Name = "ITest")]
    public interface ITestAsync
    {
        [OperationContract(AsyncPattern = true)]
        IAsyncResult BeginEcho(string text, AsyncCallback callback, object state);
        string EndEcho(IAsyncResult ar);
        [OperationContract(AsyncPattern = true)]
        IAsyncResult BeginAdd(int x, int y, AsyncCallback callback, object state);
        int EndAdd(IAsyncResult ar);
    }
    public class Service : ITest
    {
        public string Echo(string text) { return text; }
        public int Add(int x, int y) { return x + y; }
    }
    public class ServiceAsync : ITestAsync
    {
        string Echo(string text) { return text; }
        int Add(int x, int y) { return x + y; }
        public IAsyncResult BeginEcho(string text, AsyncCallback callback, object state)
        {
            Func<string, string> func = Echo;
            return func.BeginInvoke(text, callback, state);
        }

        public string EndEcho(IAsyncResult ar)
        {
            Func<string, string> func = (Func<string, string>)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate;
            return func.EndInvoke(ar);
        }

        public IAsyncResult BeginAdd(int x, int y, AsyncCallback callback, object state)
        {
            Func<int, int, int> func = Add;
            return func.BeginInvoke(x, y, callback, state);
        }

        public int EndAdd(IAsyncResult ar)
        {
            Func<int, int, int> func = (Func<int, int, int>)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate;
            return func.EndInvoke(ar);
        }
    }
    public static void Test()
    {
        foreach (bool useAsync in new bool[] { false, true })
        {
            Type contractType = useAsync ? typeof(ITestAsync) : typeof(ITest);
            Type serviceType = useAsync ? typeof(ServiceAsync) : typeof(Service);
            Console.WriteLine("Using {0} service implementation", useAsync ? "Asynchronous" : "Synchronous");
            string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
            ServiceHost host = new ServiceHost(serviceType, new Uri(baseAddress));
            host.AddServiceEndpoint(contractType, new BasicHttpBinding(), "");
            host.Open();
            Console.WriteLine("Host opened");

            Console.WriteLine("Using the same client for both services...");
            ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
            ITest proxy = factory.CreateChannel();
            Console.WriteLine(proxy.Echo("Hello"));
            Console.WriteLine(proxy.Add(3, 4));

            ((IClientChannel)proxy).Close();
            factory.Close();

            host.Close();

            Console.WriteLine("Done");
            Console.WriteLine();
        }
    }
}
于 2011-06-03T20:51:26.263 回答
1

如果通过“使服务异步”,您的意思是使用AsyncPattern,那么我的理解是这对客户端根本没有影响,只会影响 WCF 运行时如何调用您在服务器上的操作。客户端(即 WCF 客户端)一如既往地自行选择是否使用异步调用。

从这个 MSDN 页面

要定义一个异步执行的合约操作 X,无论它在客户端应用程序中如何调用...

和:

在这种情况下,异步操作以与同步操作相同的形式在元数据中公开:它被公开为带有请求消息和相关响应消息的单个操作。客户端编程模型可以选择。他们可以将此模式表示为同步操作或异步操作,只要在调用服务时发生请求-响应消息交换。

于 2011-06-03T20:40:09.150 回答
1

您的服务不必做任何“特殊”的事情……它们的行为方式仍然相同。另一方面,您的客户必须使用异步模式来使用服务。最简单的方法是使用“添加服务引用...”。只需选中一个小框,上面写着“生成异步操作”,瞧,您可以对您的服务进行异步调用......

这是一个很好的资源:如何:异步调用 WCF 服务操作

尽管有负面评论,但最后的例子很好。只需订阅<service-name>Completed事件,然后进行异步调用。调用完成后,您的 UI 线程被释放,并且一旦调用完成,就会引发事件!小心你新发现的力量!

public class Foo
{
    private BarServiceClient client;

    public Foo()
    {
        client = new BarServiceClient();
        client.DoWorkCompleted += Client_DoWorkCompleted;
    }

    private void Client_DoWorkCompleted(object sender, DoWorkCompletedEventArgs e)
    {
        //e.Result contains your result.
    }

    public void DoBar()
    {
        client.DoWorkAsync(); //Called asynchronously, UI thread is free! :)
    }
}
于 2011-06-03T20:54:49.903 回答