【问题标题】:Try catch code block not executing in Unity尝试捕获未在 Unity 中执行的代码块
【发布时间】:2021-06-07 16:52:19
【问题描述】:

我在多人项目中有一个 try-catch 语句,用于检查 Unity 中的连接状态(通过 UDP)。它在 try 代码块中接收来自服务器的回调,而 catch 代码块用于在连接突然中断的情况下获取异常。我的问题是 catch 块没有执行我用来通知用户与服务器的连接已丢失的代码。它似乎只执行与异常相关的代码(如 Debug.Error(e))。

//Callback from server connection
        private void ConnectCallback(IAsyncResult _result) {
            try {
                //Ends connection
                socket.EndConnect(_result);
            } catch (Exception e) {
                
               //These three lines are the problem. They won't execute
                UIManager.instance.logPanel.enabled = true;
                UIManager.instance.logPanel.text = "Servidor no disponible";
                UIManager.instance.HideUsernameSelection();
            }

            //If theres no connection to the server the function returns
            if (!socket.Connected) 
            {
                return;
            }

            //Reference to data stream
            stream = socket.GetStream();

            //Packet for data received from server
            receivedData = new Packet();

            //Read
            stream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveCallback, null);
        }

有没有强制catch块执行里面的代码?

【问题讨论】:

  • socket.EndConnect 似乎正在结束连接(根据代码和 MS 文档中的 cmets)。我在 try 中没有看到任何 connect 方法,那么您为什么期望捕获错误?
  • 对不起,我没有复制整个函数。我刚刚更新了它。如果连接到服务器的回调为负,我想要的是从 UIManager 执行函数,这样我就可以显示重新连接 UI 和服务器错误。

标签: c# visual-studio unity3d


【解决方案1】:

很确定问题是这个调用来自 async 等等不同的线程/任务。

大部分 Unity API 只能在 Unity 主线程上使用。 (唯一的例外是基本上所有不直接影响或依赖场景的纯数学结构。)

大多数情况下,这是通过所谓的“主线程调度程序”解决的。它看起来有点像例如

public class MainThreadDispatcher : MonoBehaviour
{
    #region Singleton Pattern
    private static MainThreadDispatcher _instance;

    public static MainThreadDispatcher Instance
    {
        get
        {
            if(_instance) return _instance;

            _instance = FindObjectOfType<MainThreadDispatcher>();
            
            if(_instance) return _instance;

            _instance = new GameObject(nameof (MainThreadDispatcher)).AddComponent<MainThreadDispatcher>();
        }  
    }

    private void Awake ()
    {
        if(_instance && _instance != this)
        {
            Destroy (gameObject);
            return;
        }

        _instance = this;
        DontDestroyOnLoad(gameObject);
    }
    #endregion

    #region Dispatcher
    private readonly Queue<Action> _actions = new Queue<Action>();

    private void LateUpdate ()
    {
        lock (_actions)
        {
            while(_actions.Count > 0)
            {
                var action = _actions.Dequeue();

                action?.Invoke();
            }
        }
    }

    public void DoInMainThread(Action action)
    {
        lock(_actions)
        {
            _actions.Enqueue(action);
        }
    }
    #endregion
}

然后你宁愿调度任何与 Unity API 相关的东西,例如

try
{
    //Ends connection
    socket.EndConnect(_result);
} 
catch (Exception e) 
{
    MainThreadDispatcher.Instance.DoInMainThread(() =>
    {
        // To have the information is always helpful I'd say ;)
        Debug.LogWarning($"{e.GetType()} - {e.Message}/n{e.StackTrace}");
        UIManager.instance.logPanel.enabled = true;
        UIManager.instance.logPanel.text = "Servidor no disponible";
        UIManager.instance.HideUsernameSelection();
    }
}

【讨论】:

  • @alex2furious,很高兴听到您的问题已经解决,您可以点击“✔”回复相应的回复。它还将帮助其他人解决类似的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-23
  • 2021-08-27
  • 2012-09-03
  • 1970-01-01
相关资源
最近更新 更多