Страница 1 из 3
Я чего-то недопонимаю в работе корутин? [РЕШЕНО]
Добавлено:
22 мар 2017, 15:10
LordWerewolf
Есть класс ConnectToServer в котором прописана корутина с логикой обмена данными с сервером.
Есть класс Registration в котором прописан метод вызывающий корутину. Он отправляет ей логин-пароль. Корутина отправляет логин-пароль дальше, на сервер и тот в свою очередь запрещает или разрешает доступ.
Есть класс InfoUser в котором тоже есть метод вызывающий ту же корутину, но передает он ей уже id пользователя. Дальше все по той же схеме: id уходит на сервер и сервер отправляет назад информацию о пользователе.
Есть еще куча других классов, которые так же обращаются к этой корутине для обмена данными с сервером.
Так вот вопрос: Почему корутина срабатывает лишь один раз, при регистрации. Дальнейшие попытки запустить ее приводят к ошибке NullReferenceException и остановке кода на строке StartCourutine(corutine()); ?
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 18:06
DbIMok
Вероятно вы обращаетесь к корутине, монобех которой уже уничтожен. Выкладывайте ваш код
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 20:19
LordWerewolf
класс с корутиной:
Используется 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()));
}
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 21:26
DbIMok
а что написано в сообщении об ошибке? потому что особого криминала в приведенном коде нет. кроме мелочей вроде создания экземпляра монобеха через new.
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 21:39
LordWerewolf
пишет такую ошибку:
NullReferenceException
UnityEngine.MonoBehaviour.StartCoroutine (IEnumerator routine) (at C:/buildslave/unity/build/artifacts/generated/common/runtime/MonoBehaviourBindings.gen.cs:54)
вот и я не вижу... не понимаю причину - это и сводит с ума. Извращаюсь уже как только могу и все бестолку...
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 21:41
LordWerewolf
я понимаю, если бы сама корутина не работала... но она работает, но только один раз
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 21:56
DbIMok
дело не в одноразовости, а в чем-то другом. простой тест
Используется 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
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 22:01
LordWerewolf
я понимаю, но мне нужно знать, где искать проблему в моем коде. Знать хотя бы что нужно переписать или дописать. Я даже не представляю в какую сторону копать...
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 22:03
seaman
Я что-то похоже тоже не понимаю
Что такое 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;
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 22:27
LordWerewolf
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;
}
... поэтому код продолжит выполняться именно после соединения.
К тому же, если бы проблема была в указанных вами местах, то корутина не должна была вообще работать. Разве не так?
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 22:36
seaman
Еще раз: Что угодно возвращайте в yield return - это будет воспринято как WaitForEndOfFrame Поэто вот это:
поэтому код продолжит выполняться именно после соединения.
неверно.
Если хотите продолжить только после коннекта делайте аналогично тому что я написал. Либо попробуйте использовать Ваш ws.Connect как корутину. Т.е. yield return StartCoroutine(ws.Connect());
Насчет того что она вообще не будет работать - я бы не сказал. Просто она работает не так как вы считаете.
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 22:56
LordWerewolf
Я пробовал уже так писать... к сожалению вылетает та-же ошибка, но уже непосредственно в самой корутине на строке yield return StartCoroutine(ws.Connect());
Сейчас попробовал ваш код, но он выдает ошибку "Оператор "!" невозможно применить к операнду типа IEnumerator!"
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 23:09
seaman
Ну естественно. Я то думал, что 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());
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 23:48
LordWerewolf
я знаю, что означает ошибка NullReferenceException. Я не могу понять, что именно ему не хватает. И ws и ConectToServer не null. Их я проверял в первую очередь. Если бы было все так очевидно...
Re: Я чего-то недопонимаю в работе корутин?
Добавлено:
22 мар 2017, 23:57
seaman
Ну во первых что значит "проверял"?
Во вторых connect то явно может быть null.
Смотри. Он существует только внутри ConnectLogin. После выход из нее неопределен.
Запускаем StartCoroutine(connect.Connecting (LogPass())); Внутри нее доходим до первой yield и возвращаем управление в ConnectLogin. Далее происходит выход из нее и connect становится неопределенным. В следующем кадре (или когда хошь) Юнити пытается вызвать Connecting, а connect-а то уже нет!
Сделай connect как я сказал. Пробовал?