ファイルがFTPの場所に到着すると、TCP経由で関連するユーザーにメッセージを送信するWindowsサービスを作成しようとしています。ファイル検出部分はすべてセットアップしましたが、メッセージング側で助けが必要です。
同時に複数のユーザーがこのサービスにサブスクライブするため、複数の接続を処理できる必要があるため、サービスの開始時に TCPServer サーバーを作成し、着信接続のリッスンを開始します。接続が到着すると、コードはその接続を接続のリストに追加します。
ここまでは順調ですね。
この問題は、着信ファイルが関連するクライアントへのメッセージの送信をトリガーするときに発生します。別のスレッドからアクセスする必要があるため、接続のリストにアクセスしようとすると失敗します (新しい接続をリッスンしているスレッドはその間他に何もできないため)。
これをデバッグ モードで実行すると、新しい接続によって ClientList のカウントが正しくインクリメントされることがわかりますが、メッセージを送信するためにデバッガがクラスに戻ると、新しい接続を作成する必要があったため、ClientList 変数が 0 にリセットされます。クラスのインスタンス。どんなアイデアでも大歓迎です。
私のコードは以下の通りです:
namespace WindowsService1
{
class MSGServer
{
TcpListener server = null;
Int32 port = 13000;
IPAddress localAddr;
List<ClientConn> ClientList = new List<ClientConn>();
Byte[] data;
private object l_lock = new object();
public void CreateServer()
{
localAddr = IPAddress.Parse("172.26.114.71");
server = new TcpListener(localAddr, port);
server.Start();
NewConnection();
}
public void NewConnection()
{
Debugger.Break();
while (true)
{
ClientConn Client = new ClientConn();
Client.TClient = server.AcceptTcpClient();
NetworkStream stream = Client.TClient.GetStream();
data = new Byte[256];
String MSG = String.Empty;
Int32 bytes = stream.Read(data, 0, data.Length);
Client.ClientUserName = Encoding.ASCII.GetString(data, 0, bytes);
stream.Write(data, 0, bytes);
lock (ClientList)
{
ClientList.Add(Client);
}
}
}
public Boolean SendNotification(string UserName, string FFolder, string FName)
{
Debugger.Break();
NetworkStream Stream;
bool MsgSent = false;
foreach (ClientConn Client in ClientList)
{
if (Client.ClientUserName == UserName)
{
Byte[] MsgByte = Encoding.ASCII.GetBytes(FFolder + "|" + FName);
Stream = Client.TClient.GetStream();
Stream.Write(MsgByte, 0, MsgByte.Length);
MsgSent = true;
}
}
return MsgSent;
}
public void CLoseAllConnections()
{
foreach (ClientConn ConnToClose in ClientList)
{
ConnToClose.TClient.Close();
}
}
}
class ClientConn
{
private string CUser;
TcpClient Client;
public string ClientUserName
{
get { return CUser;}
set { CUser = value; }
}
public TcpClient TClient
{
get { return Client; }
set { Client = value; }
}
}
}
更新: CreateServer() を実行するクラスのインスタンスを、最終的に SendNotification メソッドを呼び出すスレッドに渡すことで、以下で説明していた問題を解決しました。ご助力いただきありがとうございます