gpt4 book ai didi

c# - SL4 AsyncEventArgs 在第二个 Socket 连接后抛出 InvalidOperationException

转载 作者:行者123 更新时间:2023-12-03 12:06:49 24 4
gpt4 key购买 nike

我有一个类必须使用 Silverlight 4 中的套接字发送和接收数据。
它必须实现一个预先存在的接口(interface),所以有些事情可能看起来有些奇怪,但是
这里是:

public class TcpDataTransportClient : IDataTransportService
{
private const string TCP_ADDRESS_SETTING = "tcpaddress";
private const string TCP_PORT_SETTING = "tcpport";

private static ManualResetEvent clientConnected = new ManualResetEvent(false);
private static ManualResetEvent clientDataReceived = new ManualResetEvent(false);
private static ManualResetEvent clientDataSent = new ManualResetEvent(false);

private Dictionary<string, object> settings = new Dictionary<string, object>();
private IDataEncapsulator dataEncapsulator;
private IDataCollector dataCollector;

private Socket client;
private SocketAsyncEventArgs clientArgs;

public event DataReceivedHandler OnDataReceived;
public event DataSentHandler OnDataSent;

public TcpDataTransportClient()
{

}

public Dictionary<string, object> Settings
{
get
{
return this.settings;
}
set
{
this.settings = value;
}
}

public IDataEncapsulator DataEncapsulator
{
get
{
return this.dataEncapsulator;
}
set
{
this.dataEncapsulator = value;
}
}

public void Start(IDataCollector dataCollector)
{
this.dataCollector = dataCollector;
clientArgs = new SocketAsyncEventArgs();

client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientArgs.Completed += clientArgs_Completed;
clientArgs.UserToken = client;
clientArgs.RemoteEndPoint = GetIPEndPoint();

client.ConnectAsync(clientArgs);
clientConnected.WaitOne();
}

private IPEndPoint GetIPEndPoint()
{
IPAddress ipAddress;
int tcpPort;

if (!IPAddress.TryParse(settings[TCP_ADDRESS_SETTING].ToString(), out ipAddress))
throw new ArgumentException(String.Format("Invalid setting for IP Address: '{0}'", TCP_ADDRESS_SETTING));

if (!int.TryParse(settings[TCP_PORT_SETTING].ToString(), out tcpPort))
throw new ArgumentException(String.Format("Invalid setting for TCP Port: '{0}'", TCP_PORT_SETTING));

return new IPEndPoint(ipAddress, tcpPort);
}

void clientArgs_Completed(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Connect:
ProcessConnect(e);
break;
case SocketAsyncOperation.Receive:
ProcessReceive(e);
break;
case SocketAsyncOperation.Send:
ProcessSend(e);
break;
default:
throw new Exception("Invalid operation completed");
}
}

private void ProcessConnect(SocketAsyncEventArgs e)
{
if (e.SocketError != SocketError.Success)
{
throw new SocketException((int)e.SocketError);
}
else
{
clientConnected.Set();
}
}

private void ProcessReceive(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
var socket = e.UserToken as Socket;

var response = dataCollector.Collect(e.Buffer);

if (response != null)
{
if (this.OnDataReceived != null)
this.OnDataReceived(response);

clientDataReceived.Set();
}
else
{
bool willRaiseEvent = socket.ReceiveAsync(clientArgs);
if (!willRaiseEvent)
ProcessReceive(e);
}
}
else
{
throw new SocketException((int)e.SocketError);
}
}

private void ProcessSend(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
var socket = e.UserToken as Socket;

if (OnDataSent != null)
OnDataSent(clientArgs.Buffer);

clientDataSent.Set();
clientDataReceived.Reset();

bool willRaiseEvent = socket.ReceiveAsync(e);
if (!willRaiseEvent)
ProcessReceive(e);

clientDataReceived.WaitOne();
}
else
{
throw new SocketException((int)e.SocketError);
}
}


public void Stop()
{
client.Shutdown(SocketShutdown.Send);
client.Close();
client.Dispose();
clientArgs.Dispose();
}

public void Write(byte[] data)
{
clientDataSent.Reset();

clientArgs.SetBuffer(data, 0, data.Length);

bool willRaiseEvent = client.SendAsync(clientArgs);
if (!willRaiseEvent)
ProcessSend(clientArgs);

clientDataSent.WaitOne();
}
}

这里的想法是每个请求(发送数据)总是由响应(接收数据)回答,只要您不断开连接并创建新连接,它就可以正常工作。

例如:
client.Connect();
client.ClearConfiguration(1);
var status = client.RequestStatusDetails(1);
client.Disconnect();

此代码发送多个请求并接收每个请求的答案。
但是,如果您再次(或循环)运行相同的代码,则建立连接
但是一旦代码达到这一点:
public void Write(byte[] data)
{
clientDataSent.Reset();

clientArgs.SetBuffer(data, 0, data.Length);

bool willRaiseEvent = client.SendAsync(clientArgs);
if (!willRaiseEvent)
ProcessSend(clientArgs);

clientDataSent.WaitOne();
}

client.SendAsync(clientArgs); 会抛出异常;

这是一个异常(exception):

An asynchronous socket operation is already in progress using this SocketAsyncEventArgs instance



但是,如果您在此语句之前放置一个断点,
让VS2010打破它,然后继续调试它工作正常。

实在想不通是什么原因造成的这个问题
并且没有其他信息。

有什么建议么?

最佳答案

决定把我的评论作为答案。

恕我直言AutoResetEvent Class更适合您的需求。

AutoResetEvent clientDataSent = new AutoResetEvent(true);

public void Write(byte[] data)
{
// Wait till the Write operation gets a green light to proceed. Consider using a timeout.
clientDataSent.WaitOne();

clientArgs.SetBuffer(data, 0, data.Length);

bool willRaiseEvent = client.SendAsync(clientArgs);

// Write operation will get a signal either from ProcessSend (sync) or clientArgs_Completed (async),
if (!willRaiseEvent) ProcessSend(clientArgs);
}

void clientArgs_Completed(object sender, SocketAsyncEventArgs e)
{
bool throwInvalidOperationException = false;

switch (e.LastOperation)
{
...
default:
throwInvalidOperationException = true;
}

//Signal a waiting Write operation that it can proceed.
clientDataSent.Set();

if (throwInvalidOperationException) throw new Exception("Invalid operation completed");
}

关于c# - SL4 AsyncEventArgs 在第二个 Socket 连接后抛出 InvalidOperationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3394504/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com