いくつかのコードから始めましょう:
class InternetConnector
{
private struct ConnectionData
{
public Action<Socket> SuccessHandler { get; set; }
public ClientStateObject clientObj { get; set; }
public Action<Exception> ErrorHandler { get; set; }
public Socket Socket { get; set; }
}
public static ManualResetEvent processingDone = new ManualResetEvent( false );
public static ConcurrentQueue<string> messages = new ConcurrentQueue<string>();
public bool ReceiveMessage(Action<Socket> successHandler, Action<Exception> errorHandler)
{
ClientStateObject obj = new ClientStateObject();
obj.server = client;
var connectionData = new ConnectionData
{
ErrorHandler = errorHandler,
SuccessHandler = successHandler,
Socket = client,
clientObj = obj
};
if (Connected)
{
client.BeginReceive(connectionData.clientObj.buffer, 0, ClientStateObject.bufSize, 0, new AsyncCallback(ReceiveCallback), connectionData);
receive = true;
receiveDone.WaitOne();
}
return receive;
}
private static void ReceiveCallback(IAsyncResult ar)
{
ConnectionData connectionData = new ConnectionData();
bool complete = false;
try
{
connectionData = (ConnectionData)ar.AsyncState;
Socket client = connectionData.Socket;
int num = client.EndReceive(ar);
{
connectionData.clientObj.stringBuffer.Append(Encoding.ASCII.GetString(connectionData.clientObj.buffer, 0, num));
string response = connectionData.clientObj.stringBuffer.ToString();
string[] msgs = response.Split('&');
for (int i = 0; i < msgs.Count(); i++)
{
string sts = msgs[i];
messages.Enqueue(sts + "&" );
}
receiveDone.Set();
if (connectionData.SuccessHandler != null)
{
connectionData.SuccessHandler(client);
processingDone.WaitOne();
client.BeginReceive(connectionData.clientObj.buffer, 0, ClientStateObject.bufSize, 0, new AsyncCallback(ReceiveCallback), connectionData);
}
}
}
catch (Exception e)
{
if (connectionData.ErrorHandler != null)
connectionData.ErrorHandler(e);
}
}
public partial class Form1 : Form
{
private InternetConnector client = new InternetConnector();
private bool isRunning = false;
private void AsyncSuccessHandler(Socket socket)
{
if (InvokeRequired)
{
BeginInvoke(new Action( () => AsyncSuccessHandler( socket ) ));
return;
}
if (InternetConnector.messages.Count() == 0)
{
status.Text = "Signals Receiver: Connected";
status.ForeColor = Color.Green;
isRunning = true;
client.ReceiveMessage(AsyncSuccessHandler, AsyncErrorHandler);
}
else
{
GUIChangeOnConnection();
InternetConnector.processingDone.Set();
}
}
private void GUIChangeOnConnection()
{
for( int i = 0; i < InternetConnector.messages.Count; i++ )
{
string message;
InternetConnector.messages.TryDequeue( out message );
// process the message
}
}
}
今問題。
すべて正常に動作します。ソケットからの読み取りが行われています。ただし、への呼び出しが早すぎるprocessingDone.WaitOne();
までコールバックを無期限にブロックする必要がある呼び出し。processingDone.Set();
GUIChangeOnConnection();
- 関数の閉じ括弧行の最後にブレークポイントを設定して確認しました。ブレークポイントに到達InternetConnector.messages
し、キューが空ではないことがわかります。これは、for ループが終了していないことを意味します。そして、このブレークポイントに 2 回到達すると、キュー内のメッセージ数が急増します。
私は何を間違っていますか?それとも私のデザインが間違っているのでしょうか?
ありがとうございました。