多线程与异步方法委托调用

在写桌面应用程序的时候,可能我们经常遇到一个问题,就是当我们的程序需要处理一个非常耗时的操作,这个时间可能是一分钟,五分钟甚至更长都有可能,当然这个时候我们不可能还用单线程来跑这样的操作,因为,主线程要负责维护一个消息队列,比如界面重绘,事件处理,如果此时采用主线程去处理这样的一个操作,将会使得界面重绘无法进行响应,从而使界面冻结,程序想死掉一样无法与用户进行下一步交互。
如果解决这个问题呢?首先我们想到的应该是采用多线程。
例如新建一个线程去处理这样一个操作:
Thread thread=new Thread(new ThreadStart(Function));
thread.start();
private void Function()
{
       //处理这样的一个操作.
}
当然这样首先可以解决界面冻结,消息队列维护的问题,但是如果这样的操作可能有很多,而且是较为频繁,
如果还是采用原来的方法,每次都去新建一个线程,那样将会损耗大量的资源,因为线程之间的终止,新建,切换都有着大量的外部开销,如果线程数太多,将不利于应用程序的性能。
接着,我们可能又会换着另外一种方式来处理,马上的我们可能想到了线程池管理。
如下:
//处理一个方法,将其丢进线程池队列
ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(Function));
或许这样问题应该可以大概得到解决了,但是马上的我们又发现了新的问题,我们在新线程中的通讯无法马上响应到我们的主线程中来,以及不同线程之间访问一个控件所有可能产生的问题。
于是我们接着又用另外两种机制来解决这两个问题,用事件机制解决第一个问题,用控件委托调用解决第二个问题。
比如我们定义了一个Event,当新线程中发生了某个事件,在主线程中马上捕获这个事件,因为事件是消息队列机制的,所以程序不会“假死”,另外,我们在事件处理方法中又用委托来实现对控件的安全访问。
例如:
if(Control.InvokeRequired)
{
       Control.Invoke(new XxDeleSetControl(SetControl),value);
}
else
{
       //处理其他操作
       Control.xx=value;
}
到这里,问题基本都解决了,接着我们再说一下异步方法委托调用。其实上面的程序还可以用异步委托来完成。

//异步方法委托调用的例子
    class AsynDelegateInvokeDemo
    {
        public delegate int deleAsynCall();
        public static void Main(string[] args)
        {
            //委托绑定异步方法,该方法必须和其委托定义具有相同签名
            deleAsynCall dAsynCall = new deleAsynCall(Call);
            //开始执行异步方法,这里有两种方式,轮询与回调,另外还有一种方式WaitHandle.WaitOne()
            IAsyncResult ar = dAsynCall.BeginInvoke(null, dAsynCall);
            //IAsyncResult ar = dAsynCall.BeginInvoke(new AsyncCallback(AsynFinish), dAsynCall);
            Console.WriteLine("[main] Waiting for asynThread to finish");
            //轮询检测异步方法是否执行完成
            while(!ar.IsCompleted)
            {
                Console.Write(".");
                Thread.Sleep(500);
            }
            int ret = dAsynCall.EndInvoke(ar);
            Console.WriteLine("\r\n[AsynThread] The result is {0}", ret);
            Console.ReadLine();
        }
        //假设这里是一个长操作
        public static int Call()
        {
            int sum = 0;
            while (sum < 99999)
            {
                sum += 2000;
                Thread.Sleep(100);
            }
            return sum;
        }
        //完成回调函数
        private static void AsynFinish(IAsyncResult ar)
        {
            deleAsynCall dAsynCall=(deleAsynCall)ar.AsyncState;
            int ret = dAsynCall.EndInvoke(ar);
            Console.WriteLine("&#92;r&#92;n[AsynThread] The result is {0}", ret);
        }
    }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值