有人可以结合使用NetMQPoller和异步任务发送消息的示例吗?即
// 1. Receive a message from one of many clients
// 2. Handle client requests on multiple async Task's (may be file bound)
// 3. Respond to clients when long running Task finishes
我们当前正在使用非常准系统的“经销商/路由器”设置,以便多个客户端与单个服务器通信。在服务器上,我们将每个客户端请求传递到处理请求的任务/线程池,生成响应,然后尝试响应原始客户端。因为我是新来的,所以我没有意识到在不同的Task / Thread上调用客户端会使事情变糟,但是现在这很有意义。
我正在寻找的是正确的处理方式。我肯定可以有一个BlockingCollection消息来发送回去,并仅从原始线程中对其进行服务,但是最近我发现了 NetMQPoller ,听起来好像它内置了其中一些。我不是100%确定它是否可以帮助我在原始线程上发送消息,但是它的很多部分听起来很有希望。谁能指出我的示例,该示例是从路由器/服务器在与接收原始消息不同的线程上将消息发送回路由器/服务器的。
更新 我想我可以通过合并来解决我自己的问题
class Program
{
static void Main( string[] args )
{
// NOTES
// 1. Use ThreadLocal<DealerSocket> where each thread has
// its own client DealerSocket to talk to server
// 2. Each thread can send using it own socket
// 3. Each thread socket is added to poller
const int delay = 3000; // millis
var clientSocketPerThread = new ThreadLocal<DealerSocket>();
using( var server = new RouterSocket("@tcp://127.0.0.1:5556") )
using( var queue = new NetMQQueue<MyResponse>() )
using( var poller = new NetMQPoller { queue } )
{
// Start some threads, each with its own DealerSocket
// to talk to the server socket. Creates lots of sockets,
// but no nasty race conditions no shared state, each
// thread has its own socket, happy days.
for( int i = 0; i < 3; i++ )
{
Task.Factory.StartNew(state =>
{
DealerSocket client = null;
if( !clientSocketPerThread.IsValueCreated )
{
client = new DealerSocket();
client.Options.Identity =
Encoding.Unicode.GetBytes(state.ToString());
client.Connect("tcp://127.0.0.1:5556");
client.ReceiveReady += Client_ReceiveReady;
clientSocketPerThread.Value = client;
poller.Add(client);
}
else
{
client = clientSocketPerThread.Value;
}
while( true )
{
var messageToServer = new NetMQMessage();
messageToServer.AppendEmptyFrame();
messageToServer.Append(state.ToString());
Console.WriteLine("======================================");
Console.WriteLine(" OUTGOING MESSAGE TO SERVER ");
Console.WriteLine("======================================");
PrintFrames("Client Sending", messageToServer);
client.SendMultipartMessage(messageToServer);
Thread.Sleep(delay);
}
}, string.Format("client {0}", i), TaskCreationOptions.LongRunning);
}
queue.ReceiveReady += ( sender, e ) =>
{
var queueItem = e.Queue.Dequeue();
var messageToClient = new NetMQMessage();
messageToClient.Append(queueItem.ClientId);
messageToClient.AppendEmptyFrame();
messageToClient.Append(queueItem.MessageToClient);
server.SendMultipartMessage(messageToClient);
};
// start the poller
poller.RunAsync();
// server loop
while( true )
{
var clientMessage = server.ReceiveMultipartMessage();
Console.WriteLine("======================================");
Console.WriteLine(" INCOMING CLIENT MESSAGE FROM CLIENT ");
Console.WriteLine("======================================");
PrintFrames("Server receiving", clientMessage);
if( clientMessage.FrameCount == 3 )
{
var clientAddress = clientMessage[0];
var clientOriginalMessage = clientMessage[2].ConvertToString();
string response = string.Format("{0} back from server {1}",
clientOriginalMessage, DateTime.Now.ToLongTimeString());
Task.Factory.StartNew(async() =>
{
await Task.Delay(200);
var clientResponse = new MyResponse()
{
ClientId = clientAddress,
MessageToClient = response
};
queue.Enqueue(clientResponse);
}, TaskCreationOptions.LongRunning);
}
}
}
}
static void PrintFrames( string operationType, NetMQMessage message )
{
for( int i = 0; i < message.FrameCount; i++ )
{
Console.WriteLine("{0} Socket : Frame[{1}] = {2}", operationType, i,
message[i].ConvertToString());
}
}
static void Client_ReceiveReady( object sender, NetMQSocketEventArgs e )
{
bool hasmore = false;
e.Socket.ReceiveFrameString(out hasmore);
if( hasmore )
{
string result = e.Socket.ReceiveFrameString(out hasmore);
Console.WriteLine("REPLY {0}", result);
}
}
class MyResponse
{
public NetMQFrame ClientId;
public string MessageToClient;
}
}