namespace RoomStatusTest
{
public delegate void StatusEvent(object sender,int iStatus);
/// <summary>
/// WatchStatus 的摘要说明。
/// </summary>
public class WatchStatus:System.MarshalByRefObject
{
public event StatusEvent Status;
public Thread StatusThread;
private const string CONNSTR="Data Source=fanhui;Initial Catalog=dbname;User ID=sa;PWD=sa;Pooling=false";
private static int Proceadd=0;
private static int Procedel=0;
private static int Proceupdate=0;
private static int iRefresh=-1;
private static bool brefresh=true;
public int Refresh
{
get{return iRefresh;}
}
public WatchStatus()
{
//
// TODO: 在此处添加构造函数逻辑
//
Console.WriteLine("Begin WatchStatus"); }
/// <summary>
/// 启动线程函数,由客户端调用
/// </summary>
public void StartMyThread()
{
StatusThread=new Thread(new ThreadStart(this.Execute));
StatusThread.Name="Watch Room Status!";
StatusThread.Priority=ThreadPriority.Highest;
if(StatusThread.ThreadState==ThreadState.Unstarted)
StatusThread.Start();
}
/// <summary>
/// 线程执行函数
/// </summary>
private void Execute()
{
Status(this,1111111111);
do
{
Check();
Console.WriteLine("执行新的查询!"); Thread.Sleep(3000);
}while(true);
}
/// <summary>
/// 负责扫描数据库,并将结果事件通知客户端
/// </summary>
private void Check()
{
SqlConnection sc=new SqlConnection(CONNSTR);
sc.Open();
SqlCommand scmd=new SqlCommand("Proc_Refresh",sc);
scmd.CommandType=CommandType.StoredProcedure; scmd.Parameters.Add(new SqlParameter("@add",
SqlDbType.Int,
0,
""
));
scmd.Parameters.Add(new SqlParameter("@del",
SqlDbType.Int,
0,
""));
scmd.Parameters.Add(new SqlParameter("@update",
SqlDbType.Int,
0,
""
));
scmd.Parameters.Add(new SqlParameter("@Refresh",
SqlDbType.Int,
0,
""));
scmd.Parameters["@add"].Direction=ParameterDirection.InputOutput;
scmd.Parameters["@del"].Direction=ParameterDirection.InputOutput;
scmd.Parameters["@update"].Direction=ParameterDirection.InputOutput;
scmd.Parameters["@Refresh"].Direction=ParameterDirection.InputOutput;
scmd.Parameters["@add"].Value=WatchStatus.Proceadd;
scmd.Parameters["@del"].Value=WatchStatus.Procedel;
scmd.Parameters["@update"].Value=WatchStatus.Proceupdate;
if(WatchStatus.brefresh)
scmd.Parameters["@Refresh"].Value=-1;
else
scmd.Parameters["@Refresh"].Value=0;
WatchStatus.brefresh=false;
try
{
scmd.ExecuteNonQuery();
iRefresh=(int)scmd.Parameters["@Refresh"].Value;
Console.WriteLine("fdasfd");
switch(iRefresh)
{
case -1:
case 4:
WatchStatus.Proceadd=(int)scmd.Parameters["@add"].Value;
WatchStatus.Procedel=(int)scmd.Parameters["@del"].Value;
WatchStatus.Proceupdate=(int)scmd.Parameters["@update"].Value;
Status(this,11);
break;
case 1:
WatchStatus.Proceadd=(int)scmd.Parameters["@add"].Value;
Status(this,22);
break;
case 0:
WatchStatus.Procedel=(int)scmd.Parameters["@del"].Value;
Status(this,33);
break;
case 2:
WatchStatus.Proceupdate=(int)scmd.Parameters["@update"].Value;
Status(this,44);
break;
}
}
catch
{
}
sc.Close();
} }
}

解决方案 »

  1.   

    以上是远程对象类
    客户端调用:
    class Client
    {
    /// <summary>
    /// 应用程序的主入口点。
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
    RemotingConfiguration.Configure("../../Client.exe.config"); EventSink sink = new EventSink();
     
    WatchStatus obj=new WatchStatus();
    // register client sink in server - subscribe to event
    obj.Status += new StatusEvent(sink.StatusHandler);
    obj.StartMyThread();
    Console.WriteLine("Hit to exit");
    Console.ReadLine();
    }
    }
    -------------------------
    同时启动两个客户端,第一个启动的客户端也输出了第二个客户端启动线程时的触发事件:
    Status(this,1111111111);
    说明在服务器上为每一个客户端都启动了线程啊?!怎么才能只启动一个线程?
      

  2.   

    这肯定没有问题,我现在的项目就是这种模式的。
    在客户连接的时候,自动注册自己。这样服务端就有了所有客户端的句柄。服务端启动一个线程,查询数据之后,调用所有的客户端,发送消息过去。或者让客户端自动向服务端的DataChangeEvent注册一个delegate,服务端主动发起这个event就可以了
      

  3.   

    [email protected],谢谢简单的描述一下就好了!
      

  4.   

    to fansenwei(绿茵萤火虫):
    sample我倒是有一个,但是只是说怎么用delegate的,其实你只要自己产生一个不断查询的线程,一旦有数据变化,直接调用里面的event,把参数传给他就好了。
      

  5.   

    哦,我现在解决的方法是,在启动线程前增加一个bool判断,只当第一个对象注册时启动romoting远程对象线程。
    这样引出另一个问题,就是如果当没有客户端引用的时候要中断线程,这样就要在romoting对象上增加一个引用计数器来控制,我想知道服务器怎么知道一个客户端断开连接(不论正常断开还是死机)?
      

  6.   

    嗬嗬,其实我这里做的是可以让client注册到server上,也就是双向通讯,那么当client注册之后,server里面就有了client的reference。 然后再需要给client通知的时候直接调用client的receiveMsg,自然就能够把所有的消息转送给client乐,如果抛出通讯异常,就说明这个client断连了
      

  7.   

    哦,那不是要在Server上注册多个client的remoting object?不知道我理解的对不对
    这样你要知道每个客户端的channel了?