.net framework WebService的多线程与异步处理

先看一段WebService中的离奇代码

//这是封装了WEBSERVICE的一个上层代码

        public void AsyncPostURL(string url, string referer, string alt)
        {
            if (null == validateCode)
            {
                log.Error("AsyncPostURL:Authentication failed.");
            }
            else
            {
                if (!urlTable.ContainsKey(url))
                {
                    if (urlTable.Count <= Properties.Settings.Default.UrlHashCount)
                    {
                        urlTable.Add(url, null);
                    }
                    else
                    {
                        //url地址获得量巨大,有成片相同的特性,所以满后清除
                        urlTable.Clear();
                    }

//opt是webservice的实例,PostURLCompleted是异步方法的事件处理函数

//AsyncPostURLCompleted是最终会调用回调函数
                    opt.PostURLCompleted += new PostURLCompletedEventHandler(AsyncPostURLCompleted);
                    opt.PostURLAsync(validateCode, url, referer, alt);
                    return;
                }
                else
                {
                    log.Info("已包含的URL地址:" + url);
                }
            }
            if (null != AsyncPostURLCallBack)
            {
                AsyncPostURLCallBack();//当异步处理结束,AsyncPostURLCompleted需要调用的方法
            }
        }

 

然后再看看AsyncPostURLCompleted的代码

        private void AsyncPostURLCompleted(object sender, PostURLCompletedEventArgs e)
        {
            ((Opt)sender).PostURLCompleted -= AsyncPostURLCompleted;//离奇吧,第一行居然是移除自身作为事件回调方法
            if (null == e.Error)
            {
                log.Info("AsyncPostURLCompleted Result:" + e.Result);
            }
            else
            {
                log.Error("AsyncPostURLCompleted Result:" + e.Error.Message);
            }
            if (null != AsyncPostURLCallBack)
            {
                AsyncPostURLCallBack();
            }
        }

最后看看AsyncPostURLCallBack的代码,和调用 AsyncPostURL的代码:

                            asyncPostEmailDone = new ManualResetEvent(false);//调用代码需要建立一个单元信号
                            reporter.AsyncPostEmail(model.Url, model.Referer, model.Alt);
                            asyncPostEmailDone.WaitOne();//这里表示同时只能调用一个

        private void AsyncPostURLProcess()
        {
            if (null != asyncPostURLDone)
            {
                asyncPostURLDone.Set();//重置,上面的代码可以再次运行
            }
        }

 

从这些代码中不难看出,WebService的异步处理,其实并非线程安全的,一个WebService对象里的所有异步方法,在同时只能一个方法运行。

而且,是在类似ThreadPool中,用QueueItem的方式运行。是会按照时刻不断的运行下去,好比ThreadPool.QueueUserWorkItem(AsyncPostURL);每次被调用后,移除事件处理,就是为了防止内部重复调用,而使用ManualResetEvent对象,却是为了在外部防止重复调用。不难看出,WebService的异步处理整个就是个麻烦。

 

ManualResetEvent对象只能作为多个线程之间的一个事件通知作用。要保证代码在多线程下同时只能被一个线程访问,还是需要Monitor(用于保证实例同一时间只被单个线程访问)。

 Mutex.WaitOne和ReleaseMutex的组合能保证一段代码同时只被一个线程访问,Mutex还可以用命名的形式来完成进程间的同步。其实这些在Windows API中都有现成的模型。.Ner Framework只是封装了这些API。方式都没有变

 

泛型对象的同步,这里只用Queue<T>来说明一下

当对Queue使用两个线程分别作Enqueue何Dequeue操作时,一直没有碰到线程同步问题,搞的我以为Queue是同步的,后来,将两个线程都调用Enqueue方法,问题就来了,会有异常。可见Queue并非是一个同步对象,在其操作开始处使用Monitor.Enter,结束使用Monitor.Exit是很有必要的,或者使用Lock也行。

 

注意:在.Net FrameWork中,所有的异步处理都是使用ThreadPool中的线程。如果某个异步操作十分缓慢,那么线程耗尽是必然的。SO,,,这玩意还是给那些偶然性处理的事件比较好。不管是多线程,还是异步处理(DMA除外).都只有占有更多的CPU才能保证获得更多的处理时间,获得整体上的速度优势,一味的使用多线程并没有必要。只有当应用上需要时,才可以考虑使用多线程。反之,远远不如多开一个进程,这样不但数据有多个实例,方法也是。能够占用更多的CPU。使得针对于多线程同步问题而在代码中的额外开销得以避免。真要提高速度,还得在优化设计和算法上下功夫。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值