Я использую игровой движок Unity для создания сетей и хочу использовать встроенные языковые функции, а не полагаться на сторонние ресурсы или Unity API. Я придумал этот компонент, который присоединяется к GameObject. Когда игровой объект включен, он должен отправлять UDP-пакеты в указанное место назначения.
Эта часть работает. Проблема, с которой я сталкиваюсь, связана с этим флагом sending
:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using UnityEngine;
namespace UdpTest
{
public class DummySender : MonoBehaviour
{
public string destinationAddress = "127.0.0.1";
public int port = 55555;
UdpClient client;
bool sending;
IPEndPoint endpoint;
private void Awake()
{
client = new UdpClient();
try
{
endpoint = new IPEndPoint(IPAddress.Parse(destinationAddress), port);
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000);
client.Connect(endpoint);
}
catch (Exception e)
{
Debug.LogError("Couldn't set up dummy sender: " + e.Message, gameObject);
gameObject.SetActive(false);
}
}
private void OnEnable()
{
sending = true;
new Task(() =>
{
try
{
Debug.Log("Ready to send");
while (sending)
{
var bytes = System.Text.Encoding.ASCII.GetBytes(DateTime.Now.Millisecond.ToString() + "\n");
client.Send(bytes, bytes.Length);
}
}
catch (Exception e)
{
Debug.LogError("Dummy send failed: " + e.Message);
}
}).Start();
}
private void OnDisable()
{
sending = false;
}
}
}
Проблема, с которой я столкнулся, заключается в том, что я не могу остановить ее после запуска задачи с l oop. .
Мой план состоял в том, чтобы остановить его, когда компонент отключен, установив для флага sending
значение false. Я понимаю, что установка флага в false происходит в другом потоке. Я ожидал, что да, l oop может запускаться еще несколько раз между флагом sending
, установленным в false, и задачей, получающей доступ к его значению, но это хорошо для моих целей.
Однако в действительности происходит то, что задача, кажется, никогда не осознает, что значение sending
изменилось. Он остается true
, l oop работает бесконечно, и мой получатель не прекращает получать пакеты, пока я не убью программу.
Почему это? Я немного новичок в низкоуровневых задачах / потоках, но я понимаю, что нет никакой гарантии, что рабочая задача немедленно узнает об изменении. Я ожидал бы, что это обновится в конечном счете. Но в моем случае, хотя я могу убедиться, что флаг sending
был установлен в false в главном потоке, l oop в задаче никогда не останавливается.
Если бы мне пришлось угадывать, это кажется как ошибка того же рода, что и при копировании значения и изменении оригинала (то есть ошибка по ссылке / по значению). Есть ли у задачи копия sending
, а не ссылка на поле экземпляра класса? Или я что-то упускаю?
Я знаю, что есть другие стратегии для достижения UDP-связи, например, использование вариантов Async
, но ради обучения я хотел бы знать, что я делаю неправильно здесь и как это исправить, не меняя тактику полностью.