问题
I edited my question when I set the bounty. I want to Invoke/DllImport WSAAsyncSelect() from WinAPI and use it much like I use it in Delphi/C++
For example - Delphi
//Async CallBack handler Declaration
procedure MessageHandler(var Msg:Tmessage);Message WM_WINSOCK_ASYNC_MSG;
//Where i setup the Async
dwError := WSAAsyncSelect(Sock, form1.handle, WM_WINSOCK_ASYNC_MSG, FD_CLOSE or FD_READ);
//Async Callback Handler
procedure Tform1.MessageHandler(var Msg:Tmessage);
begin
case WSAGetSelectEvent(MSG.LParam) of //LParam is FD_READ/FR_CLOSE/FD_WRITE
FD_READ: OnSocketRead(MSG.WParam); //WPARAM is the Socket itself.
FD_CLOSE: OnSocketClose(MSG.WParam);
end;
end;
Thanks in advance!
回答1:
I made it! Finaly!!!
WSAAsyncSelect() structure
[DllImport("wsock32.dll")]
public static extern int WSAAsyncSelect(
int socket,
int hWnd,
int wMsg,
int lEvent
);
WS2 Class
public class WS2
{
public static Socket sock;
public static byte[] data = new byte[8096];
public static int server = 0;
public static bool forced = true;
public static void Close()
{
//Extern.closesocket(sock.Handle.ToInt32());
//Extern.WSACleanup();
sock.Shutdown(SocketShutdown.Both);
sock.Close();
if (forced)
{
Connect();
}
}
public static void ConnectTo(string ip,int port)
{
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.Connect(ip, port);
int handle = 0;
var form1 = Form.ActiveForm as FormMain;
if (form1 != null)
handle = form1.GetHandle;
if (handle == 0)
{
FormMain.PerformActionOnMainForm(form => form.memo.Text += "An error occured: Error code WS_01_ASYNC_HANDLE");
return;
}
Extern.WSAAsyncSelect(sock.Handle.ToInt32(), handle, Values.MESSAGE_ASYNC, Values.FD_READ | Values.FD_CLOSE);
}
public static void Connect()
{
//Get IP && port
string ip = GetIPFromHost("gwgt1.joymax.com");
if (ip == "")
{
ip = GetIPFromHost("gwgt2.joymax.com");
if (ip == "")
{
}
server +=2;
}
else
server +=1;
int port = 15779;
//
ConnectTo(ip, port);
}
public static void Receive()
{
int size = sock.Receive(data);
if (size == 0)
{
FormMain.PerformActionOnMainForm(form => form.memo.Text += "An error occured: Error Code WS_02_RECV_BEGN");
}
Main.Handle(data, size);
}
public static string GetIPFromHost(string HostName)
{
IPHostEntry ip;
try
{
ip = Dns.GetHostEntry(HostName);
}
catch (Exception)
{
return "";
}
return ip.AddressList[0].ToString();
}
}
WndProc in the Form class.
protected override void WndProc(ref Message m)
{
if (m.Msg == Values.MESSAGE_ASYNC)
{
switch (m.LParam.ToInt32())
{
case Values.FD_READ:
WS2.Receive();
break;
case Values.FD_WRITE: break;
case Values.FD_CLOSE:
WS2.Close();
break;
default: break;
}
}
else
{
base.WndProc(ref m);
}
}
Get Handle:
public int GetHandle
{
get
{
if (this.InvokeRequired)
{
return (int)this.Invoke((GetHandleDelegate)delegate
{
return this.Handle.ToInt32();
});
}
return this.Handle.ToInt32();
}
}
private delegate int GetHandleDelegate();
回答2:
(edit: relates mainly to the original question, before it was edited and a bounty added)
I've been looking at this problem recently - see Async without the pain. Note the comment at the end about using the delegate version - this simplifies the calling slightly.
As an update, the final code would look something like below, and as it transpires is very similar to what F# uses under the bonnet:
public static void RunAsync<T>(
Func<AsyncCallback, object, IAsyncResult> begin,
Func<IAsyncResult, T> end,
Action<Func<T>> callback) {
begin(ar => {
T result;
try {
result = end(ar); // ensure end called
callback(() => result);
} catch (Exception ex) {
callback(() => { throw ex; });
}
}, null);
}
来源:https://stackoverflow.com/questions/686355/how-to-invoke-and-use-wsaasyncselect-in-c