在一个控制台程序里,定义一个委托加入一个方法实例化后,用BeginInvoke进行异步调用,同时增加一个回调方法,回调方法里面用EndInvoke结束异步调用,如下面代码所示。但是执行的时候,程序一闪就完了,加入委托的方法根本不执行。为了能让控制台程序不至于一闪就执行完,我在程序的最后加入readkey,使主程序停在那里,一段时间后检查,增加到委托里面的方法执行了。这个问题很奇怪,难道是需要设置组线程为前台线程,怎么管理主线程与工作线程之间的关系呢? 委托的BeginInvoke 应该是工作线程执行委托里面的方法吧。
(注:增加到委托里面的方法有两个线程,分别向不同的数据库更新数据)private delegate void DelegateDispatchMsg(string DataGroup, string ReferenceId, List<MsgInfo> Msgs, int NumberOfMessages);
DelegateDispatchMsg delegateDispatchMsg = new DelegateDispatchMsg(DispatchMsg);
delegateDispatchMsg.BeginInvoke(DataGroup, ReferenceId, Msgs, NumberOfMessages, new AsyncCallback(CallBackMethod), list);
Console.ReadKey();//为增加主线程的执行时间
        private void CallBackMethod(IAsyncResult ar)
        {
            ArrayList list = (ArrayList)ar.AsyncState;
            string DataGroup = (string)list[0];
            string ReferenceId = (string)list[1];
            List<MsgInfo> Msgs = (List<MsgInfo>)list[2];
            int NumberOfMessages = (int)list[3];
            DateTime start = (DateTime)list[4];
            DelegateDispatchMsg delegateDispatchMsg = (DelegateDispatchMsg)list[5];            delegateDispatchMsg.EndInvoke(ar);            if (_IsSuccessful)
                Log.DBLog(ReferenceId, DataGroup, NumberOfMessages, start, DateTime.Now, "S");
            else
                Log.DBLog(ReferenceId, DataGroup, NumberOfMessages, start, DateTime.Now, "F");
        }

解决方案 »

  1.   

    这个问题很奇怪,难道是需要设置组线程为前台线程,怎么管理主线程与工作线程之间的关系呢? >>>>>>>>>我就不知道这里有啥奇怪的你不是已经知道了吗?
    BeginInvoke方法会在线程池里开一个线程来执行,而线程池的线程是后台线程,无法维持进程,所以当主线程结束的时候,后台线程也被迫终止了,当你加了ReadKey之后,由于主线程存在,所以后台线程能正常工作
      

  2.   

    看来在控制台程序里面不能用异步来实现等待了,只有另外再开线程,等待前一个线程执行完,再来执行原来回调函数里面的方法了,请问CsToD,有没有办法实现一个线程等待另一个线程执行完毕才开始执行的方法呢,能不能讲一下思路?谢谢
      

  3.   

    等待线程完成,Thread.Join方法。
      

  4.   

    定义一个字段
    Thread t;
    然后在委托的方法里赋值
    t=Thread.CurrentThread;
    然后在主线程调用t.Join()方法但是有个小问题,由于是异步的,t.Joint方法很可能比t=Thread.CurrentThread先执行
    从来导致null调用
    所以可以在t.Join上先调用一下Thread.Sleep(200);
    保证t赋值先与t的调用
      

  5.   

    但是我的疑问是,你为什么不在主线程调用EndInvoke,而非要在回调方法里调用?
      

  6.   

    在主线程调用EndInvoke应该要轮询才行,有可能异步调用没完成,主线程就执行了EndInvoke了。已经想到办法了,就是轮询异步返回的IAsyncResult的IsComplete属性,没完成就阻塞,知道完成了再调用EndInvoke。
      

  7.   


    汗....你完全就没理解......
    EndInvoke本来就是等待异步调用结束,如果异步调用没有执行完,EndInvoke会一直挂起,直到其结束
      

  8.   

    是的,EndInvoke确实是要等到BeginInvoke执行完才执行的。如果没有必要监视BeginInvoke的状态,就直接在后面调用EndInvoke就可以了
      

  9.   

            delegate int AddHandler(int a, int b);        private void button1_Click(object sender, EventArgs e)
            {
                Thread thread = null;
                AddHandler add = new AddHandler((a, b) =>
                {
                    thread = Thread.CurrentThread;
                    System.Threading.Thread.Sleep(10000);
                    return a + b;
                });
                var ar = add.BeginInvoke(1, 2, iar => { }, add);            if (!ar.AsyncWaitHandle.WaitOne(1000, true))
                {
                    thread.Abort();
                    //ar.AsyncWaitHandle.Close();
                    textBox1.Text = "timeout!";
                }
                else
                {
                    textBox1.Text = add.EndInvoke(ar).ToString();
                    ar.AsyncWaitHandle.Close();
                }
            }