我有一個C++管道服務器應用程序和一個C#管客戶端應用程序通過Windows命名管道的通信(全雙工,消息模式,等待/在單獨的讀取線程阻塞)。雙工命名管道掛在某些寫
這一切工作正常(發送和通過管道接收數據),直到我嘗試寫來自客戶端的管道響應形式的「框TextChanged」事件。當我這樣做時,客戶端掛在管道寫入呼叫上(或者在自動刷新關閉的情況下刷新呼叫)。打入服務器應用程序顯示它也在等待管道ReadFile調用,而不是返回。 我試圖運行客戶端寫在另一個線程 - 相同的結果。
可疑某種死鎖或競爭條件的,但看不到的地方......別以爲我同時寫入到管道。
Update1:嘗試管道在字節模式而不是消息模式 - 相同的鎖定。
UPDATE2:奇怪的是,如果(且僅當)我抽大量的數據從服務器到客戶端,它能治癒死機!?
Server代碼:
DWORD ReadMsg(char* aBuff, int aBuffLen, int& aBytesRead)
{
DWORD byteCount;
if (ReadFile(mPipe, aBuff, aBuffLen, &byteCount, NULL))
{
aBytesRead = (int)byteCount;
aBuff[byteCount] = 0;
return ERROR_SUCCESS;
}
return GetLastError();
}
DWORD SendMsg(const char* aBuff, unsigned int aBuffLen)
{
DWORD byteCount;
if (WriteFile(mPipe, aBuff, aBuffLen, &byteCount, NULL))
{
return ERROR_SUCCESS;
}
mClientConnected = false;
return GetLastError();
}
DWORD CommsThread()
{
while (1)
{
std::string fullPipeName = std::string("\\\\.\\pipe\\") + mPipeName;
mPipe = CreateNamedPipeA(fullPipeName.c_str(),
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
KTxBuffSize, // output buffer size
KRxBuffSize, // input buffer size
5000, // client time-out ms
NULL); // no security attribute
if (mPipe == INVALID_HANDLE_VALUE)
return 1;
mClientConnected = ConnectNamedPipe(mPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (!mClientConnected)
return 1;
char rxBuff[KRxBuffSize+1];
DWORD error=0;
while (mClientConnected)
{
Sleep(1);
int bytesRead = 0;
error = ReadMsg(rxBuff, KRxBuffSize, bytesRead);
if (error == ERROR_SUCCESS)
{
rxBuff[bytesRead] = 0; // terminate string.
if (mMsgCallback && bytesRead>0)
mMsgCallback(rxBuff, bytesRead, mCallbackContext);
}
else
{
mClientConnected = false;
}
}
Close();
Sleep(1000);
}
return 0;
}
客戶端代碼:
public void Start(string aPipeName)
{
mPipeName = aPipeName;
mPipeStream = new NamedPipeClientStream(".", mPipeName, PipeDirection.InOut, PipeOptions.None);
Console.Write("Attempting to connect to pipe...");
mPipeStream.Connect();
Console.WriteLine("Connected to pipe '{0}' ({1} server instances open)", mPipeName, mPipeStream.NumberOfServerInstances);
mPipeStream.ReadMode = PipeTransmissionMode.Message;
mPipeWriter = new StreamWriter(mPipeStream);
mPipeWriter.AutoFlush = true;
mReadThread = new Thread(new ThreadStart(ReadThread));
mReadThread.IsBackground = true;
mReadThread.Start();
if (mConnectionEventCallback != null)
{
mConnectionEventCallback(true);
}
}
private void ReadThread()
{
byte[] buffer = new byte[1024 * 400];
while (true)
{
int len = 0;
do
{
len += mPipeStream.Read(buffer, len, buffer.Length);
} while (len>0 && !mPipeStream.IsMessageComplete);
if (len==0)
{
OnPipeBroken();
return;
}
if (mMessageCallback != null)
{
mMessageCallback(buffer, len);
}
Thread.Sleep(1);
}
}
public void Write(string aMsg)
{
try
{
mPipeWriter.Write(aMsg);
mPipeWriter.Flush();
}
catch (Exception)
{
OnPipeBroken();
}
}
您在服務器端處理讀取錯誤看起來有點不禮貌。作爲一種診斷手段,我建議你暫時更改服務器,以便在發生讀取錯誤時退出,這樣就可以確定客戶端的寫入和服務器端的讀取與同一個管道相關。 –
通過更改服務器來嘗試簡化情況也許會有所幫助,以便它不會將任何數據寫入管道,以便可以將客戶端設置爲單線程。如果這不能消除問題,至少可以確定它不是某種線程問題。 –
Chris:添加了代碼:) @Harry:它固執地坐在ReadFile fn中,甚至沒有返回錯誤。建議多管道......見下文。嘗試沒有服務器寫入:相同的結果。仍然在尋找...: -/ – MGB