私の質問にはイベントが含まれており、クラス内のイベントをトリガしています。このクラスは私のTCP機能をラップし、これを実現するためにTcpListenerを使用しています。私はいくつかのTCPのものは、以下の例から消失する可能性が実現するが、私はできるだけシンプルなものを作りたい:#2.0サンプルCでのAsyncCallbackからのトリガーイベント
class MyTcpClass
{
public delegate void ClientConnectHandler(Socket client, int clientNum);
public event ClientConnectHandler ClientConnect;
private Socket wellKnownSocket;
private Socket[] clientSockets = new Socket[MAX_CLIENTS];
private int numConnected = 0;
private void OnClientConnect(Socket client, int clientNum)
{
if (ClientConnect != null)
ClientConnect(client, clientNum);
}
public void StartListening()
{
//initialize wellKnownSocket
//...
wellKnownSocket.BeginAccept(new AsyncCallback(internal_clientConnect);
}
public void internal_clientConnect(IAsyncResult ar)
{
//Add client socket to clientSocket[numConnected]
//numConnected++;
//...
wellKnownSocket.EndAccept(ar);
OnClientConnect(clientSocket[numConnected], numConnected);
//error: event happens on different thread!!
}
}
class MainForm
{
void Button_click()
{
MyTcpClass mtc = new MyTcpClass();
mtc.ClientConnect += mtc_ClientConnected;
}
void mtc_clientConnected(Socket client, int clientNum)
{
ActivityListBox.Items.Add("Client #" + clientNum.ToString() + " connected.");
//exception: cannot modify control on seperate thread
}
}
C
私は私の質問があると思い、あまりにもこのパターンを壊すことなく、多くの意味がありますか?また、誰かがより優雅なソリューションを持っている場合は、歓迎します。
理論
class MainForm
{
public MainForm()
{
MyTcpClass mtc = new MyTcpClass();
MyTcpClass2 mtc2 = new MyTcpClass2(this);
//this version holds a Form handle to invoke the event
mtc.ClientConnect += mtc_uglyClientConnect;
mtc2.ClientConnect += mtc2_smartClientConnect;
}
//This event is being called in the AsyncCallback of MyTcpClass
//the main form handles invoking the control, I want to avoid this
void mtc_uglyClientConnect(Socket s, int n)
{
if (mycontrol.InvokeRequired)
{
//call begininvoke to update mycontrol
}
else
{
mycontrol.text = "Client " + n.ToString() + " connected.";
}
}
//This is slightly cleaner, as it is triggered in MyTcpClass2 by using its
//passed in Form handle's BeginInvoke to trigger the event on its own thread.
//However, I also want to avoid this because referencing a form in a seperate class
//while having it (the main form) observe events in the class as well seems... bad
void mtc2_smartClientConnect(Socket s, int n)
{
mycontrol.text = "Client " + n.ToString() + " connected.";
}
}
最初の例をお勧めします。ここでは、呼び出しを使用してMainFormのイベントハンドラ内のwinformコントロールにアクセスしますか?私は、MyTcpClassがどのスレッド上にあるのか気付かないでくださいが、MyTcpClassには、クライアントとの非同期コールバック関係があります。私は、MyTcpClassが作成されたスレッドではなく、スレッドでイベントをトリガーしたいと思っています。私はあなたの意見を見て、それに同意しますが、Microsoft自身がprogresschangedイベントで "backgroundworker"という同様のイベントをモデル化します。 –
@Tom:問題は、このスレッドモデルがWinformsに特有であることです。クラスが作成されたスレッドでイベントハンドラを呼び出すことさえできないことがあります。 (スレッドが終了した場合はどうなりますか?) – cdhowie