我正在開發一個通信API供很多通用客戶端用來與專有系統進行通信。幾個客戶端在等待相同的事件
這個專有系統公開了一個API,我使用一個特定的類來發送和等待來自這個系統的消息:很顯然,系統提醒我使用事件準備好了消息。該事件被命名爲OnMessageArrived。
我的想法是公開一個簡單的SendSyncMessage(消息)方法,它可以幫助用戶/客戶端簡單地發送消息,並且該方法返回響應。
客戶端:
using (Communicator c = new Communicator())
{
response = c.SendSync(message);
}
通信器類以這種方式完成的:
public class Communicator : IDisposable
{
// Proprietary system object
ExternalSystem c;
String currentRespone;
Guid currentGUID;
private readonly ManualResetEvent _manualResetEvent;
private ManualResetEvent _manualResetEvent2;
String systemName = "system";
String ServerName = "server";
public Communicator()
{
_manualResetEvent = new ManualResetEvent(false);
//This methods are from the proprietary system API
c = SystemInstance.CreateInstance();
c.Connect(systemName , ServerName);
}
private void ConnectionStarter(object data)
{
c.OnMessageArrivedEvent += c_OnMessageArrivedEvent;
_manualResetEvent.WaitOne();
c.OnMessageArrivedEvent-= c_OnMessageArrivedEvent;
}
public String SendSync(String Message)
{
Thread _internalThread = new Thread(ConnectionStarter);
_internalThread.Start(c);
_manualResetEvent2 = new ManualResetEvent(false);
String toRet;
int messageID;
currentGUID = Guid.NewGuid();
c.SendMessage(Message, "Request", currentGUID.ToString());
_manualResetEvent2.WaitOne();
toRet = currentRespone;
return toRet;
}
void c_OnMessageArrivedEvent(int Id, string root, string guid, int TimeOut, out int ReturnCode)
{
if (!guid.Equals(currentGUID.ToString()))
{
_manualResetEvent2.Set();
ReturnCode = 0;
return;
}
object newMessage;
c.FetchMessage(Id, 7, out newMessage);
currentRespone = newMessage.ToString();
ReturnCode = 0;
_manualResetEvent2.Set();
}
}
我真的很小白使用WaitHandle的,但我的想法是創建一個發送的一個實例消息並等待事件。一旦事件到達,檢查消息是否是我期望的消息(檢查唯一的GUID),否則繼續等待下一個事件。 這是因爲可能(並且通常以這種方式)很多客戶同時工作,並且我希望他們能夠並行工作。 正如我實現我的東西,此刻如果我運行客戶端1,客戶端2和客戶端3,客戶端2開始發送消息一旦客戶端1完成,客戶端3作爲客戶端2已完成:不是我想要的去做。
你能幫我解決我的代碼,並得到我的目標?
謝謝!
我比較了字符串對象,因爲我在事件中收到的guid是一個字符串。 對於_AutoResetEvent2,問題是我有點困惑。如果是「我的」指導,我想停下來等待並做一些邏輯,否則我想繼續等待。 你認爲這是做到這一點的正確方法嗎? 爲什麼現在有幾個客戶端是序列化的? – ff8mania
對不起,忽略了,看到更新回覆 – sll
謝謝!所以:我沒有發佈dispose方法來避免進一步的代碼,但是在Dispose方法中我斷開了我的c和Set()的manualResetEvent(之前的autoResetEvet)。 public void Dispose() {c。斷開(); _manualResetEvent.Set(); } – ff8mania