[英]Processing received UDP data in another thread in C#
我有一個包含在單獨線程中接收UDP數據的方法的類。 我這樣做是為了避免主應用程序(在Unity3D中運行)停頓。
我需要將在單獨線程中接收到的數據傳遞給另一個類,該類在原始線程上運行,因此能夠與Unity3D進行交互。
UDPReceiver大致如下所示:
public class UDPReciever {
//...
public UDPReciever() {
m_Port = 12345;
m_Worker = new Thread(new ThreadStart(recvData));
m_Worker.IsBackground = true;
m_Worker.Start();
}
void recvData() {
m_UDPClient = new UdpClient(m_Port);
while (true) {
try {
IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
byte[] data = (m_UDPClient.Receive(ref anyIP));
// TODO: Hand 'data' to NetworkController class (running in the original thread) for processing
} catch (Exception err) {
print(err.ToString());
}
}
}
}
這大致就是NetworkController類的外觀。 理想情況下,每次接收到一個新的數據包,並將數據作為參數傳遞時,都將調用“ OnNewData”方法。
public class NetworkController {
//...
void OnNewData(pData) {
// Process the data in this thread
}
}
我將如何實現這一目標? 提前致謝。
這是完成的方式(未經測試):
public class Dispatcher : MonoBehaviour
{
private static readonly BlockingCollection<Action> tasks = new BlockingCollection<Action>();
public static Dispatcher Instance = null;
static Dispatcher()
{
Instance = new Dispatcher();
}
private Dispatcher()
{
}
public void InvokeLater(Action task)
{
tasks.Add(task);
}
void FixedUpdate()
{
if (tasks.Count > 0)
{
foreach (Action task in tasks.GetConsumingEnumerable())
{
task();
}
}
}
}
...
NetworkController networkControllerInstance;
void recvData()
{
m_UDPClient = new UdpClient(m_Port);
while (true)
{
try
{
IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
byte[] data = (m_UDPClient.Receive(ref anyIP));
Dispatcher.Instance.InvokeLater(() => networkControllerInstance.OnNewData(data));
}
catch (Exception err)
{
print(err.ToString());
}
}
}
編輯:
應符合.Net 3.5的版本 :
public class Dispatcher : MonoBehaviour
{
private static readonly Queue<Action> tasks = new Queue<Action>();
public static Dispatcher Instance = null;
static Dispatcher()
{
Instance = new Dispatcher();
}
private Dispatcher()
{
}
public void InvokeLater(Action task)
{
lock (tasks)
{
tasks.Enqueue(task);
}
}
void FixedUpdate()
{
while (tasks.Count > 0)
{
Action task = null;
lock (tasks)
{
if (tasks.Count > 0)
{
task = tasks.Dequeue();
}
}
task();
}
}
}
編輯2:
如果要避免在太長的時間內凍結主線程:
void FixedUpdate()
{
if (tasks.Count != 0)
{
Action task = null;
lock (tasks)
{
if (tasks.Count != 0)
{
task = tasks.Dequeue();
}
}
task();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.