Я чего-то недопонимаю в работе корутин? [РЕШЕНО]

Форум для самых маленьких, а так же тех, кому недосуг читать справку самостоятельно.

Я чего-то недопонимаю в работе корутин? [РЕШЕНО]

Сообщение LordWerewolf 22 мар 2017, 15:10

Есть класс ConnectToServer в котором прописана корутина с логикой обмена данными с сервером.
Есть класс Registration в котором прописан метод вызывающий корутину. Он отправляет ей логин-пароль. Корутина отправляет логин-пароль дальше, на сервер и тот в свою очередь запрещает или разрешает доступ.
Есть класс InfoUser в котором тоже есть метод вызывающий ту же корутину, но передает он ей уже id пользователя. Дальше все по той же схеме: id уходит на сервер и сервер отправляет назад информацию о пользователе.
Есть еще куча других классов, которые так же обращаются к этой корутине для обмена данными с сервером.

Так вот вопрос: Почему корутина срабатывает лишь один раз, при регистрации. Дальнейшие попытки запустить ее приводят к ошибке NullReferenceException и остановке кода на строке StartCourutine(corutine()); ?
Последний раз редактировалось LordWerewolf 27 мар 2017, 18:40, всего редактировалось 1 раз.
LordWerewolf
UNIт
 
Сообщения: 81
Зарегистрирован: 04 апр 2016, 13:20

Re: Я чего-то недопонимаю в работе корутин?

Сообщение DbIMok 22 мар 2017, 18:06

Вероятно вы обращаетесь к корутине, монобех которой уже уничтожен. Выкладывайте ваш код
правильный вопрос - половина ответа. учитесь формулировать вопросы понятно.
Новости > _Telegram чат @unity3d_ru (11.6k/4.8k online) > _Telegram канал @unity_news (4.7k подписчиков) > Телеграм тема > "Спасибо"
Аватара пользователя
DbIMok
Адепт
 
Сообщения: 6372
Зарегистрирован: 31 июл 2009, 14:05

Re: Я чего-то недопонимаю в работе корутин?

Сообщение LordWerewolf 22 мар 2017, 20:19

класс с корутиной:
Синтаксис:
Используется csharp
public class ConnectToServer : MonoBehaviour
{
    string answer = "";
    bool getdatafromserver = false;
    public string Connect_text;
    public WebSocket ws;
    public delegate void ChekingAnswer();
    public event ChekingAnswer answerFromServer;

    public IEnumerator Connecting(string s)
    {
        Debug.Log("Подключаем сокет...");
        ws = new WebSocket(new Uri("ws://localhost:8080"));
        yield return ws.Connect();
        Debug.Log("Сокет подключен.");
        Debug.Log("отправляем запрос:" + s);
        try
        {
            ws.SendString(s);
        }
        catch { Debug.LogError("Запрос не отправлен!"); }
        do {
            answer = ws.RecvString();
            if (ws.error != null)
            {
                Debug.LogError("Error: " + ws.error);
            }
            if (!string.IsNullOrEmpty(answer))
            {
                Debug.Log("ответ получен: " + answer);
                Connect_text = answer;
                answer = "";
                ws.Close();
                if (answerFromServer != null)
                {
                    answerFromServer();
                }
                else { Debug.LogError("answerFromServer not working!"); }
                break;
            }
        } while (true);
        ws.Close();
        yield return null;
    }
}
 


функция вызова...
Синтаксис:
Используется csharp
public void ConnectLogin()
{
        ConnectToServer connect = new ConnectToServer();
        connect.answerFromServer += AutorizationCheck;
        StartCoroutine(connect.Connecting (LogPass()));
}
 
LordWerewolf
UNIт
 
Сообщения: 81
Зарегистрирован: 04 апр 2016, 13:20

Re: Я чего-то недопонимаю в работе корутин?

Сообщение DbIMok 22 мар 2017, 21:26

а что написано в сообщении об ошибке? потому что особого криминала в приведенном коде нет. кроме мелочей вроде создания экземпляра монобеха через new.
правильный вопрос - половина ответа. учитесь формулировать вопросы понятно.
Новости > _Telegram чат @unity3d_ru (11.6k/4.8k online) > _Telegram канал @unity_news (4.7k подписчиков) > Телеграм тема > "Спасибо"
Аватара пользователя
DbIMok
Адепт
 
Сообщения: 6372
Зарегистрирован: 31 июл 2009, 14:05

Re: Я чего-то недопонимаю в работе корутин?

Сообщение LordWerewolf 22 мар 2017, 21:39

пишет такую ошибку:
NullReferenceException
UnityEngine.MonoBehaviour.StartCoroutine (IEnumerator routine) (at C:/buildslave/unity/build/artifacts/generated/common/runtime/MonoBehaviourBindings.gen.cs:54)

вот и я не вижу... не понимаю причину - это и сводит с ума. Извращаюсь уже как только могу и все бестолку... :((
LordWerewolf
UNIт
 
Сообщения: 81
Зарегистрирован: 04 апр 2016, 13:20

Re: Я чего-то недопонимаю в работе корутин?

Сообщение LordWerewolf 22 мар 2017, 21:41

я понимаю, если бы сама корутина не работала... но она работает, но только один раз :-??
LordWerewolf
UNIт
 
Сообщения: 81
Зарегистрирован: 04 апр 2016, 13:20

Re: Я чего-то недопонимаю в работе корутин?

Сообщение DbIMok 22 мар 2017, 21:56

дело не в одноразовости, а в чем-то другом. простой тест
Синтаксис:
Используется csharp
using System.Collections;
using UnityEngine;

public class NewBehaviourScript {
        public IEnumerator TestCor() {
                Debug.LogFormat("TestCor 1");
                yield return null;
                Debug.LogFormat("TestCor 2");
        }
}

Синтаксис:
Используется csharp
using UnityEngine;

public class NewBehaviourScript1 : MonoBehaviour {
        void OnGUI () {
                if (GUI.Button(new Rect(5, 5, 100, 20), "Test")) {
                        var script = new NewBehaviourScript();
                        StartCoroutine(script.TestCor());
                }
        }
}

выводит
Изображение
если унаследовать NewBehaviourScript от MonoBehaviour то это не изменит поведения, только добавит warning
правильный вопрос - половина ответа. учитесь формулировать вопросы понятно.
Новости > _Telegram чат @unity3d_ru (11.6k/4.8k online) > _Telegram канал @unity_news (4.7k подписчиков) > Телеграм тема > "Спасибо"
Аватара пользователя
DbIMok
Адепт
 
Сообщения: 6372
Зарегистрирован: 31 июл 2009, 14:05

Re: Я чего-то недопонимаю в работе корутин?

Сообщение LordWerewolf 22 мар 2017, 22:01

я понимаю, но мне нужно знать, где искать проблему в моем коде. Знать хотя бы что нужно переписать или дописать. Я даже не представляю в какую сторону копать...
LordWerewolf
UNIт
 
Сообщения: 81
Зарегистрирован: 04 апр 2016, 13:20

Re: Я чего-то недопонимаю в работе корутин?

Сообщение seaman 22 мар 2017, 22:03

Я что-то похоже тоже не понимаю
Что такое ws.Connect()?
Просто в yield return должно быть что-то, что наследуется от yieldInstruction либо null/break. Можно всунуть что угодно, но это будет трактоваться просто как WaitForEndOfFrame.
Обсуждалось тут: http://gamedev.stackexchange.com/questi ... -c-scripts
и тут http://answers.unity3d.com/questions/63 ... ner-636147
Т.е. у Вас управление на строку после yield должно вернутся не когда будет установлено соединение, а в следующем кадре. Т.е. по сути корутина совсем не выполняет своих функций.
Дальше программа будет висеть в цикле пока не придет что-то в ответ. Что вообще имхо неприемлемо.
Ну, и как уже заметили не создавайте MonoBehaviour через new...
Чтобы делало что вы хотели нужно что-то типа:
Синтаксис:
Используется csharp
    public IEnumerator Connecting(string s)
    {
        Debug.Log("Подключаем сокет...");
        ws = new WebSocket(new Uri("ws://localhost:8080"));
        while(!ws.Connect())  yield return null;
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Я чего-то недопонимаю в работе корутин?

Сообщение LordWerewolf 22 мар 2017, 22:27

ws.connect() - это функция из обертки websocket-sharp. По сути это Enumerator... вот так он выглядит в плагине:
Синтаксис:
Используется csharp
public IEnumerator Connect()
        {
                m_Socket = new WebSocketSharp.WebSocket(mUrl.ToString());
                m_Socket.OnMessage += (sender, e) => m_Messages.Enqueue (e.RawData);
                m_Socket.OnOpen += (sender, e) => m_IsConnected = true;
                m_Socket.OnError += (sender, e) => m_Error = e.Message;
        m_Socket.ConnectAsync();
        while (!m_IsConnected && m_Error == null)
                        yield return null;
        }

... поэтому код продолжит выполняться именно после соединения.
К тому же, если бы проблема была в указанных вами местах, то корутина не должна была вообще работать. Разве не так?
LordWerewolf
UNIт
 
Сообщения: 81
Зарегистрирован: 04 апр 2016, 13:20

Re: Я чего-то недопонимаю в работе корутин?

Сообщение seaman 22 мар 2017, 22:36

Еще раз: Что угодно возвращайте в yield return - это будет воспринято как WaitForEndOfFrame Поэто вот это:
поэтому код продолжит выполняться именно после соединения.

неверно.
Если хотите продолжить только после коннекта делайте аналогично тому что я написал. Либо попробуйте использовать Ваш ws.Connect как корутину. Т.е. yield return StartCoroutine(ws.Connect());
Насчет того что она вообще не будет работать - я бы не сказал. Просто она работает не так как вы считаете.
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Я чего-то недопонимаю в работе корутин?

Сообщение LordWerewolf 22 мар 2017, 22:56

Я пробовал уже так писать... к сожалению вылетает та-же ошибка, но уже непосредственно в самой корутине на строке yield return StartCoroutine(ws.Connect());
Сейчас попробовал ваш код, но он выдает ошибку "Оператор "!" невозможно применить к операнду типа IEnumerator!"
LordWerewolf
UNIт
 
Сообщения: 81
Зарегистрирован: 04 апр 2016, 13:20

Re: Я чего-то недопонимаю в работе корутин?

Сообщение seaman 22 мар 2017, 23:09

Ну естественно. Я то думал, что ws.Connect() возвращает bool
Отчего NullReferenceException? Нужно думать - что null? Сначала возникает мнение, что "вы обращаетесь к корутине, монобех которой уже уничтожен". Вроде это не так. Что другое? ws и ConnectToServer могут быть null. ws навряд ли, но можно проверить, а вот ConnectToServer скорее всего.
Можно попробовать определить ws не в классе, а внутри корутины а вот ConnectToServer наоборот в классе.
Синтаксис:
Используется csharp
ConnectToServer connect;
public void ConnectLogin()
{
        connect = new ConnectToServer();
        connect.answerFromServer += AutorizationCheck;
        StartCoroutine(connect.Connecting (LogPass()));
}

Синтаксис:
Используется csharp
    public IEnumerator Connecting(string s)
    {
        Debug.Log("Подключаем сокет...");
        var ws = new WebSocket(new Uri("ws://localhost:8080"));
        yield return StartCoroutine(ws.Connect());
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Я чего-то недопонимаю в работе корутин?

Сообщение LordWerewolf 22 мар 2017, 23:48

я знаю, что означает ошибка NullReferenceException. Я не могу понять, что именно ему не хватает. И ws и ConectToServer не null. Их я проверял в первую очередь. Если бы было все так очевидно... :((
LordWerewolf
UNIт
 
Сообщения: 81
Зарегистрирован: 04 апр 2016, 13:20

Re: Я чего-то недопонимаю в работе корутин?

Сообщение seaman 22 мар 2017, 23:57

Ну во первых что значит "проверял"?
Во вторых connect то явно может быть null.
Смотри. Он существует только внутри ConnectLogin. После выход из нее неопределен.
Запускаем StartCoroutine(connect.Connecting (LogPass())); Внутри нее доходим до первой yield и возвращаем управление в ConnectLogin. Далее происходит выход из нее и connect становится неопределенным. В следующем кадре (или когда хошь) Юнити пытается вызвать Connecting, а connect-а то уже нет!
Сделай connect как я сказал. Пробовал?
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

След.

Вернуться в Почемучка

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 31