首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Queue<Action>的主线程协同线

使用Queue<Action>的主线程协同线
EN

Stack Overflow用户
提问于 2014-10-21 08:17:12
回答 1查看 2.1K关注 0票数 1

当我从websockets获得一些数据并试图通过协同机制显示数据时,我遇到了一些小麻烦。

首先,我将一个classA附加到一个打开websocket并显示接收到的数据的对象上:

代码语言:javascript
复制
public class ClassA : MonoBehaviour {

     ...

     public IEnumerator ConnectWebSocket(url)
     {
       // in the websocket class, start the websocket connection, which
       // will return data through a callback inside the return string
       WebSocketClass.WebSocketStart(url, delegate(string result)
       {
         // receive websocket data and call the functions that displays it
         WebSocketData(result);
       });

       // wait for the socket connection
       while (WebSocketClass.WebSocketGetState() == WebSocketSharp.WebSocketState.CONNECTING)
       {
         yield return 0;
       }

       if (WebSocketClass.WebSocketGetState() == WebSocketSharp.WebSocketState.OPEN)
       {
          break;
       }

       ...

    }

     // function that gets websocket data and starts couroutine to display it
     public void WebSocketData(string data)
     {
       StartCoroutine(DisplayMessage(data));       
     }
}

但是联合抱怨下一个错误:

只能从主线程调用StartCoroutine_Auto。在加载场景时,将从加载线程执行构造函数和字段初始化程序。不要在构造函数或字段初始化器中使用此函数,而是将初始化代码移动到“唤醒”或“启动”函数。

我在团结论坛上搜索并找到了这样的解决方案:

代码语言:javascript
复制
public class ClassA : MonoBehaviour {

  ...

  public IEnumerator ConnectWebSocket(url)
  {
    // in the websocket class, start the websocket connection, which
    // will return data through a callback inside the return string
    WebSocketClass.WebSocketStart(url, delegate(string result)
    {
      // receive websocket data and call the functions that displays it
      WebSocketData(result);
    });

    // wait for the socket connection
    while (WebSocketClass.WebSocketGetState() == WebSocketSharp.WebSocketState.CONNECTING)
    {
      yield return 0;
    }

    if (WebSocketClass.WebSocketGetState() == WebSocketSharp.WebSocketState.OPEN)
    {
       break;
    }

    ...

  }

  // function that gets websocket data and starts couroutine to display it
  public void WebSocketData(string data)
  {
    DoOnMainThread.ExecuteOnMainThread.Enqueue(() => { StartCoroutine(DisplayMessage(data)); });    
  }
}

// class to manage the websocket data display inside the main thread
public class DoOnMainThread : MonoBehaviour 
{

  public readonly static Queue<Action> ExecuteOnMainThread = new Queue<Action>();

  public virtual void Update()
  {
    // dispatch stuff on main thread
    while (ExecuteOnMainThread.Count > 0)
    {
      ExecuteOnMainThread.Dequeue().Invoke();
    }
  }
}

而且起作用了!问题是,即使我在同一个cs文件中编写了这两个类并附加到一个对象,但当我更改场景时,返回到该场景,并从websocket接收任何数据,下一个错误将显示:

MissingReferenceException:类型'ClassA‘的对象已被销毁,但您仍在尝试访问它。您的脚本应该检查它是否为null,或者不应该销毁该对象。C:/BuildAgent/work/d63dfc6385190b60/artifacts/EditorGenerated/UnityEngineMonoBehaviour.cs:62) ( UnityEngine.MonoBehaviour.StartCoroutine ) (IEnumerator例程)

在加载新场景时,我试图不销毁该对象,如文档所述:

代码语言:javascript
复制
void Awake()
    {
        DontDestroyOnLoad(transform.gameObject);
    }

但错误仍然出现。

奇怪的是,虽然有一个错误,从websocket接收到的数据显示没有任何问题。

有人知道如何避免这个问题吗?有没有办法在不使用第二个类的情况下触发主线程内的协同线?或其他避免此错误的解决方案?

谢谢!

EN

回答 1

Stack Overflow用户

发布于 2014-10-21 09:08:09

我发现了问题:

代码语言:javascript
复制
public readonly static Queue<Action> ExecuteOnMainThread = new Queue<Action>();

它是静态的,所以当一个公共类被实例化并生成另一个ExecuteOnMainThread时,它就成了一个问题。

因此,只要删除“静态”,并使其破坏和生成自己,每次ClassA是由统一。

现在它就像一种魅力:)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26481929

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档