Hololens开发(10) WCF接收信息

前面确认了在Hololens(Unity)中能够使用WCF,测试的方式是调用服务,但是并没有接收数据。

注意:在Unity中无法使用Asyn和Task<>。

使用Async会出现:error CS1644: Feature `asynchronous functions' cannot be used because it is not part of the C# 4.0 language specification

使用Task,直接找不到该类。


1.Unity中如何使用WCF

前面在Unity中使用WCF是通过接口

在Unity中定义接口

    public interface IWCFClient
    {
        void SendString(string msg);

        void TestReceive(int count);

        void Test();
    }
以及一个单例对象(静态类也行)

public class WCFClientFactory: IWCFClient
    {
        public  static WCFClientFactory Instance=new WCFClientFactory();

        public IWCFClient Client;

        public void SendString(string msg)
        {
            if (Client != null)
            {
                Client.SendString(msg);
            }
            else
            {
                Debug.Log(msg);
            }
        }

        public void Test()
        {
            if (Client != null)
            {
                Client.Test();
            }
            else
            {
                Debug.Log("WCFClientFactory.Test");
            }
        }

        public void TestReceive(int count)
        {
            if (Client != null)
            {
                Client.TestReceive(count);
            }
            else
            {
                Debug.Log("WCFClientFactory.TestReceive");
            }
        }
    }
注意这里的 public IWCFClient Client;

然后在UWP(启动项目中)添加服务引用,在App中初始化Client

        public App()
        {
            this.InitializeComponent();
            SetupOrientation();
            appCallbacks = new AppCallbacks();

            ServiceClientFactory.Test();
            WCFClientFactory.Instance.Client=new WCFClient();
        }
    public class WCFClient:IWCFClient
    {
        public async void SendString(string msg)
        {
            CommonServiceClient client = ServiceClientFactory.GetCommonServiceClient("192.168.253.1");
            await client.SendStringAsync(msg);
            await client.CloseAsync();
        }

        public void Test()
        {
            ServiceClientFactory.Test();
        }

        public async void TestReceive(int count)
        {
            CommonServiceClient client = ServiceClientFactory.GetCommonServiceClient("192.168.253.1");
            string msg=await client.GetStringAsync(count, "a");
            await client.CloseAsync();
            ServiceClientFactory.Log("Receive:" + msg.Length);
        }
    }
public static class ServiceClientFactory
    {
        public static void Test()
        {
            Log("Start Test");
            TestCommonServiceClient();
        }

        public static CommonServiceClient GetCommonServiceClient(string ip)
        {
            NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
            binding.MaxReceivedMessageSize = int.MaxValue;
            EndpointAddress endpointAddress = new EndpointAddress("net.tcp://" + ip + ":8001/CommonService");
            CommonServiceClient currentClient = new CommonServiceClient(binding, endpointAddress);
            return currentClient;
        }

        public static async void TestCommonServiceClient()
        {
            try
            {
                CommonServiceClient client = GetCommonServiceClient("192.168.253.1");
                await client.HelloAsync("TestClient");
                await client.GetStringAsync(10, "A");
                await client.SendStringAsync("ABCD");
                await client.CloseAsync();
            }
            catch (Exception ex)
            {
                Log(ex.Message);
            }
        }

        public static async void Log(string msg)
        {
            CommonServiceClient client = GetCommonServiceClient("192.168.253.1");
            await client.SendStringAsync("[Log]:"+msg);
            await client.CloseAsync();
        }
    }
最后,在Unity脚本中使用

public class Commands : MonoBehaviour {

	void OnSelect()
    {
        if (!this.GetComponent<Rigidbody>())
        {
            var rigidbody = this.gameObject.AddComponent<Rigidbody>();
            rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous;

            WCFClientFactory.Instance.SendString("Commands.OnSelect");
        }
    }

前面写了TestRecevie相关的代码,但是,现在实际上是无法将返回信息显示在Unity中的。


2.显示返回信息

Unity中:

IWCFClient添加

string ReceiveString(int count);
WCFClientFactory添加

        public string ReceiveString(int count)
        {
            if (Client != null)
            {
                return Client.ReceiveString(count);
            }
            else
            {
                Debug.Log("WCFClientFactory.RecevieString");
                return "";
            }
        }
UWP中:

WPFClient中添加

        public string ReceiveString(int count)
        {
            CommonServiceClient client = ServiceClientFactory.GetCommonServiceClient("192.168.253.1");
            string msg = await client.GetStringAsync(count, "a");
            await client.CloseAsync();
            return msg;
        }
结果

await必须和async配对,async的函数必须是void 或者 Task 或者 Task<T>

如果将string改成Task<string>的话,接口就要改,就改到Unity中了,在UWP环境中是可以改的,回到Unity环境就不行了。

改成用回调函数的方式:

Unity中:

IWCFClient修改

void ReceiveString(int count,Action<string> callback);

WCFClientFactory修改

        public void ReceiveString(int count, Action<string> callback)
        {
            if (Client != null)
            {
                Client.ReceiveString(count, callback);
            }
            else
            {
                Debug.Log("WCFClientFactory.RecevieString");
                if (callback != null)
                {
                    callback("");
                }
            }
        }

UWP中:

WPFClient中修改

        public async void ReceiveString(int count, Action<string> callback)
        {
            CommonServiceClient client = ServiceClientFactory.GetCommonServiceClient("192.168.253.1");
            string msg = await client.GetStringAsync(count, "a");
            await client.CloseAsync();
            if (callback != null)
            {
                callback(msg);
            }
        }
Unity脚本调用,OnSelect是 Hololens开发(9)中的点击后调用的函数

public class TestReceive : MonoBehaviour {

    public int Count = 1;

    private void OnSelect()
    {
        TestResult.Intance.Write("TestReceive.OnSelect");
        gameObject.transform.Translate(Vector3.up);
        WCFClientFactory.Instance.ReceiveString(Count, msg =>
        {
            TestResult.Intance.Append("Msg:" + msg);
        });
    }
可以!

TestResult脚本

using UnityEngine;
using UnityEngine.UI;

public class TestResult : MonoBehaviour {

    public static TestResult Intance;

    public Text text;

    private string _txt;

    private bool _isDirty;

    void Awake()
    {
        Intance = this;
    }

    void Update()
    {
        if (_isDirty)
        {
            Write(_txt);
            _isDirty = false;
        }
    }

    public void WriteAsync(string msg)
    {
        _isDirty = true;
        _txt = msg + "\n";
    }

    public void AppendAsync(string msg)
    {
        _isDirty = true;
        _txt += msg + "\n";
    }

    public void Write(string msg)
    {
        Debug.Log(msg);
        try
        {
            text.text = msg + "\n";
        }
        catch (System.Exception ex)
        {
            text.text = ex.ToString();
        }
       
    }

    public void Clear()
    {
        text.text = "";
    }

    public void Append(string msg)
    {
        Debug.Log(msg);
        try
        {
            text.text += msg+"\n";
        }
        catch (System.Exception ex)
        {
            text.text = ex.ToString();
        }
    }
}
注意:因为async是异步调用,也就是子线程,在Unity中子线程里面是不能修改Object这些Unity物体的,在线程中也不能修改UI的,需要通过Update来执行相应的回调函数行为(显示结果到UI上)。不然会抛出异常,另外因为异常是在子线程中抛出的,必须在子线程中接。








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值