异步客户端调用异步WCF服务器以获得反馈.NET 3.5

时间:2015-06-12 13:56:01

标签: c# wcf asynchronous service

我正在尝试从现有的慢速同步WCF服务功能实现异步反馈。所以我按照MSDN示例熟悉: https://msdn.microsoft.com/en-us/library/ms731177(v=vs.90).aspx

我重用了示例中的CompletedAsyncResult。主机WCF服务:

[ServiceContract]
    public interface IService
    {
        [OperationContract]
        string SlowHelloWorld(string msg);

        [OperationContract(AsyncPattern = true)]
        IAsyncResult BeginFeedback(string msg, AsyncCallback callback, object asynState);

        string EndFeedback(IAsyncResult result);
    }

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class Service : IService
    {
        public string SlowHelloWorld(string msg)
        {
            Console.WriteLine("SlowHelloWorld called with: \"{0}\"", msg);
            Thread.Sleep(5000);

            return "Hello world " + msg;
        }

        public IAsyncResult BeginFeedback(string msg, AsyncCallback callback, object asynState)
        {
            Console.WriteLine("BeginServiceAsyncMethod called with: \"{0}\"", msg);
            return new CompletedAsyncResult<string>(msg);
        }

        public string EndFeedback(IAsyncResult r)
        {
            CompletedAsyncResult<string> result = r as CompletedAsyncResult<string>;
            Console.WriteLine("EndServiceAsyncMethod called with: \"{0}\"", result.Data);
            Thread.Sleep(1000);

            return result.Data;
        }
    }

创建主持人:

 internal class Program
    {
        private static void Main(string[] args)
        {
            Uri addr = new Uri("net.tcp://localhost:4588");

            NetTcpBinding binding = new NetTcpBinding();
            binding.Security.Mode = SecurityMode.None;

            Service service = new Service();
            var host = new ServiceHost(service, addr);
            host.AddServiceEndpoint(typeof(IService), binding, "Message");
            host.Open();

            Console.ReadKey();
        }
    }

客户:

private static void Main(string[] args)
        {
            var binding = new NetTcpBinding();
            binding.Security.Mode = SecurityMode.None;
            var endpoint = new EndpointAddress("net.tcp://localhost:4588/Message");
            var channelFactory = new ChannelFactory<IService>(binding, endpoint);

            IService client = null;

            try
            {
                Mutex mutex = new Mutex();
                var numberOfThreads = 10;

                var message = "I am Client";
                client = channelFactory.CreateChannel();

                int globalValue = 0;
                for (int i = 0; i < numberOfThreads; i++)
                {
                    var thread = new Thread(() =>
                    {
                        // increment counter safely
                        mutex.WaitOne();
                        var threadValue = globalValue;
                        globalValue++;
                        mutex.ReleaseMutex();

                        // wait for slow hello world to start before calling async method
                        Thread.Sleep(500);

                        var res = client.BeginFeedback(
                            threadValue.ToString(),
                            delegate(IAsyncResult r)
                            {
                                var result = client.EndFeedback(r);
                                Console.WriteLine(result);
                            },
                            null);
                    });

                    thread.Start();
                }

                Console.WriteLine(client.SlowHelloWorld(message));

                Console.ReadKey();
                ((ICommunicationObject)client).Close();
            }
            catch
            {
                if (client != null)
                {
                    ((ICommunicationObject)client).Abort();
                }
            }
        }

忽略退货订单无法保证的事实。

这个解决方案给了我错误的结果,因为慢速方法完成然后线程可以完成他们的工作ala:

Hello world I am Client
1
0
3
6
2
9
8
4
7
5

接下来我发现了一些提示,我可能错误地调用了客户端函数: https://stackoverflow.com/questions/22590239/calling-async-methods-from-a-wcf-service/22591516#22591516 http://geekswithblogs.net/MarkPearl/archive/2011/10/12/async-using-the-old-async-begin--end-pattern.aspx https://stackoverflow.com/questions/448487/is-there-a-way-to-get-error-feedback-on-asynchronous-wcf-calls

所以我继续试图以异步方式调用主机方法,希望如此。

  public delegate void MethodInvoker();

并将Thread方法改为:

client.BeginFeedback(
                            threadValue.ToString(),
                            delegate(IAsyncResult r)
                            {
                                var invoker = new MethodInvoker(delegate()
                                {
                                    var result = client.EndFeedback(r);
                                    Console.WriteLine(result);
                                });

                                invoker.Invoke();
                            },
                            null);

结果相同。

尝试异步调用慢速方法(希望如此):

public delegate string AsyncMethodCaller(string message);

        var caller = new AsyncMethodCaller(client.SlowHelloWorld);
        caller.BeginInvoke(
            message,
            new AsyncCallback(delegate(IAsyncResult result)
            {
                AsyncResult beginResult = (AsyncResult)result;

                AsyncMethodCaller endCaller = (AsyncMethodCaller)beginResult.AsyncDelegate;

                var endResult = endCaller.EndInvoke(beginResult);

                Console.WriteLine(endResult);
            }),
            null);

仍然没有运气。这些似乎暗示ConcurrencyMode在主机端必须是Multiple。但没有区别。 https://stackoverflow.com/questions/17080037/async-wcf-self-hosted-service https://stackoverflow.com/questions/11264825/accessing-persession-service-simultaneously-in-wcf-using-c-sharp

这个似乎是我想要的,向现有的同步接口添加异步功能,但我不能使用await,async和Task作为.Net 3.5 https://stackoverflow.com/questions/27882501/how-to-add-async-support-to-a-net-4-5-wcf-service-so-it-doesnt-disrupt-existin

所以问题: 我缺少什么/我不了解异步WCF通信?

我调用的所有服务方法是否也必须遵循异步模式?包括长时间运行的方法。

0 个答案:

没有答案