繁体   English   中英

C#WCF将数据从服务器上运行的任务传递到客户端

[英]C# WCF pass data from Task running on Server to Client

我是WCF地区的新手。 我想在服务器上制作屏幕截图,并使用WCF nettcpbinding将其发送给客户端。 在客户端上,我想使用这些数据更新UI。 但是我不知道我需要什么以及如何做到这一点。 我读了有关带回调的全双工合同,但我不知道这是否确实需要。

WPFClient.cs

namespace WPFClient
{
    [ServiceContract]
    interface IService
    {
        [OperationContract]
        byte[] GetData();
    }

    public class ViewModel : INotifyPropertyChanged
    {
        private string bytesSum;

        public string BytesSum
        {
            get { return bytesSum; }
            set { bytesSum = value; this.NotifyPropertyChanged("BytesSum"); }
        }


        public ViewModel()
        {
            ChannelFactory<IService> channel = new ChannelFactory<IService>(new NetTcpBinding(), new EndpointAddress(@"net.tcp://localhost:8554/"));
            IService s = channel.CreateChannel();
            //How to get data from server and update UI?
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

Server.cs

namespace Server
{
    [ServiceContract]
    interface IService
    {
        [OperationContract]
        byte[] GetData();
    }

    public class Service : IService
    {
        public byte[] GetData()
        {
            byte[] result = new byte[5000];
            return result;
        }
    }

    public class ScreenLogger
    {
        public byte[] GenerateImage()
        {
            byte[] result = new byte[5000];
            Random rnd = new Random();
            for (int i = 0; i < result.Length; i++)
            {
                result[i] = (byte)rnd.Next();
            }
            return result;
        }

        public void Start()
        {
            var imageTask = Task.Factory.StartNew(() =>
            {
                byte[] GeneratedBytes = GenerateImage();
                //How to send GeneratedBytes to client?
            });
        }

        public void Stop()
        {

        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ScreenLogger screenLogger = new ScreenLogger();
            screenLogger.Start();

            ServiceHost host = new ServiceHost(typeof(Service));
            host.AddServiceEndpoint(typeof(IService), new NetTcpBinding(), new Uri(@"net.tcp://localhost:8554/"));
            Console.WriteLine("Server start");
            host.Open();
            Console.ReadLine();
            host.Close();
        }
    }
}

您的IService接口不是双工合同。 它应该指定客户端(即客户端应用程序中的视图模型)实现的回调协定。 然后,服务器端的服务实现将在回调上调用操作。

您可以在服务实现中使用OperationContext类获得对回调的引用,如下所示:

var callback = OperationContext.Current.GetCallbackChannel<IYourDuplexCallback>();

然后,您调用回调方法将数据从服务器传递到客户端。 还有就是如何创建和安装MSDN上提供双工WCF服务的例子在这里

如何:创建双工合同: https //docs.microsoft.com/zh-cn/dotnet/framework/wcf/feature-details/how-to-create-a-duplex-contract

在我看来,根据您的示例所执行的操作,看起来您只需要在服务实例可用的空间中获取Task的结果即可。

我的简化版本具有服务合同和实施的属性:

[ServiceContract]
public interface IService
{
    // not exposed 
    byte[] TaskResults { get; set; }

    [OperationContract]
    byte[] GetData();
}

public class Service : IService
{
    public byte[] TaskResults { get; set; }
    public byte[] GetData()
    {
        //byte[] result = new byte[5000];
        //return result;
        return TaskResults;
    }
}

然后将ScreenLogger.Start()签名更改为ScreenLogger.Start(Action<byte[]> bytesAction) ,以任务工作的结果调用该动作。

public void Start(Action<byte[]> bytesAction)
    {
        var imageTask = Task.Factory.StartNew(() =>
                                                  {
                                                      //var GeneratedBytes = GenerateImage();

                                                      //How to send GeneratedBytes to client?
                                                      bytesAction(GenerateImage());
                                                  });
    }

最后传递一个将任务结果分配给service属性的动作。

static void Main(string[] args)
    {
        ScreenLogger screenLogger = new ScreenLogger();
        ServiceHost host = new ServiceHost(typeof(Service));

        screenLogger.Start(ba => ((Service)host.SingletonInstance).TaskResults = ba);

        host.AddServiceEndpoint(typeof(IService), new NetTcpBinding(), new Uri(@"net.tcp://localhost:8554/"));
        Console.WriteLine("Server start");
        host.Open();
        Console.ReadLine();
        host.Close();
    }

客户端代码(简化)如下所示。

public class ViewModel 
{
    private string bytesSum;

    public string BytesSum
    {
        get { return bytesSum; }
        set { bytesSum = value; this.NotifyPropertyChanged("BytesSum"); }
    }


    public ViewModel()
    {
        ChannelFactory<IService> channel = new ChannelFactory<IService>(new NetTcpBinding(), new EndpointAddress(@"net.tcp://localhost:8554/"));
        IService s = channel.CreateChannel();

        //How to get data from server and update UI?
        s.GetData().ToList().ForEach(b => Console.Write(b));
    }


    private void NotifyPropertyChanged(String propertyName = "")
    {

    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM