照我的理解,这好像是asp的问题。

解决方案 »

  1.   

    IIS+ASP是个很复杂的环境,个人强烈推荐你阅读下面文章:Title: House of COM Q&A, MSJ September, 1998
    http://www.microsoft.com/MSJ/0998/com0998.htm你会茅塞顿开。 :-)- 微软全球技术中心 VC技术支持 本贴子以“现状”提供且没有任何担保,同时也没有授予任何权利。具体事项可参见使用条款 
    (http://support.microsoft.com/directory/worldwide/zh-cn/community/terms_chs.asp)。 
    为了为您创建更好的讨论环境,请参加我们的用户满意度调查 
    (http://support.microsoft.com/directory/worldwide/zh-cn/community/survey.asp?key=(S,49854782))。
      

  2.   

    我明白了,原来ASP运行时把每个请求都放在一个中央请求队列里,由ASP管理的线程池中的STA线程监视该队列并以先进先出的方式处理请求,这也就是为什么你的两个请求不能并发的原因。
      

  3.   

    to zhang1976(被大风刮的到处跑) 那么在ASP中的脚本却能并发?
      

  4.   

    to zhang1976(被大风刮的到处跑) 那么在ASP中的脚本却能并发?
      

  5.   

    ASP不就是服务器端的脚本吗?
      

  6.   

    asp脚本确实不能并发。
    你做一个很简单的试验,在一个asp脚本里头弄一个死循环。如果你访问了这个页面,那么同个目录底下(按微软的说法,就是同个应用程序)的asp页面的访问都会被阻塞了。
      

  7.   

    我告诉你:
    线程池里有25个辅助线程,每次ASP运行时从线程池里调用一个空闲线程处理队列里的请求,所以感觉上ASP脚本像是在并发。而你采用的是BOTH,这样当一个STA线程实例化对象,那么这个对象也就驻留在这个特定的STA中,客户通过这个STA线程访问这个对象,那么你在调用这个对象的任何方法时,自然还得排着队,当然不能并发了。
      

  8.   

    哦,那么微软的ASP说他能并发处理大量用户的请求岂不是吹牛了??
    他为什么不采用MTA或NA方式呢?
      

  9.   

    If the in-process class is ed ThreadingModel=Free or has no ThreadingModel attribute, the object will be created on a COM-managed thread and the ASP script will get a proxy. This is not ASP magic—it's just how COM works. Because the object's methods will execute on a COM-managed thread within the process, the object's methods will execute using the credentials of the process (either the SYSTEM account for in-process ASP applications or the IWAM_MACHINENAME account for out-of-process ASP applications). Also, since a thread switch is needed for each method call, method invocation will be considerably slower. 上面这段话的意思是现程模式设为Free,就不用ASP来管理吗但是这样作好像没有任何效果啊?有谁看懂了http://www.microsoft.com/MSJ/0998/com0998.htm请告诉我,这篇文章提出了解决方法了吗?
    谢谢
      

  10.   

    单处理器的并发不就是排队后的线程切换问题嘛!如果想要真的并发,那么就加装多个CPU吧!
      

  11.   

    单处理器上的并发当然不是真的并发,只是让人看起来在并发而已,
    但是他也不能在一个现程中分配长时间的CPU而不切换吧。
    现在的问题是系统在一个方法内阻塞,而不是多个CPU的问题
      

  12.   

    to zhang1976(被大风刮的到处跑) 
    Free不行to fftongzhi(程序员也爱家)
    唉,可惜
      

  13.   

    谈谈我的理解
    那段话的意思是若ThreadingModel=Free或没设置线程模式在ASP创建组件时该组件实际是创建在COM-managed thread中,并不在当前的STA中(IIS为ASP请求创建的都是STA)当前的STA只得到了一个PROXY,此时多个STA对该组件的调用仍是经过同步的。解决方法是用FTA在COM+中称为线程中立,就是不通过STA的消息机制而用独立的同步机制这样可使不同STA并发调用组件的方法。
    yangmajituipo() 的问题其实也很好理解。问题的关键在于COM作为DLL在一个EXE中只会创建一个实例,第一个创建他的线程拥有对象,而其他的线程则只拥有对象的PROXY,或引用。于是
    1。两个VB客户端是两个EXE,各拥有一个COM实例,用SLEEP挂掉一个还有一个于是并发没问题。
    2.一个VB客户端一个浏览器(实际创建组件的进程是IIS,IIS将统一目录下的ASP视为一个应用)同1并发没问题。
    3。两个浏览器,实际调用的是一个IIS下的同一个应用,这是IIS只创建了一个组件实例,IIS会为不同客户的ASP请求创建不同的STA来响应,拥有组件的是第一个创建组件的STA,而另一个支拥有一个PROXY,调用被自动同步,对该组件的调用是同步的,非并发。解决方法仍是使用FTA这样两个STA中对组件的调用可并发。但问题是你调用的是SLEEP,这将导致拥有该组件的STA挂掉,组件都挂掉了,其他线程自然要等待,断然没法实现并发了。没辙了。
    个人觉得MS在ASP的并发机制并不怎么样。感谢 acptvc(微软全球技术中心 VC技术支持)
    http://www.microsoft.com/MSJ/0998/com0998.htm
    是篇不错的文章,“茅厕顿开”谈不上,管中窥豹罢了。
      

  14.   

    说得有一定道理,一度让我以为问题得以解决,但是事实证明不对你可以不用Sleep阻塞现程,用GetTickCount得到该方法运行时间,然后用该Time作文件名(避免在文件重名等待)打印启动时间,执行一个费时的操作,打映结束时间,可以发现多个现程运行时,仍然是串行的。(启动时间均在上一方法执行完后,大家可以实验)并发真的不能实现吗??
      

  15.   

    问题的关键在于COM作为DLL在一个EXE中只会创建一个实例???是这样吗?那么多个用户之间岂不是互相干扰了。应该是只有一个COMModule
    吧.并且在同一客户端执行程序中,开多个线程,每个线程创建同一组件,可以看到,即使用Sleep,也能并发
      

  16.   

    你再次操作前实现了FTS了吗?,若没有,你的COM只在一个STA中运行,其他的STA只得到PROXY调用该线程的方法时时通过消息机制的,当然会被同步。
    “拥有组件的是第一个创建组件的STA,而另一个支拥有一个PROXY,调用被自动同步,对该组件的调用是同步的,非并发。”所得就是这个意思,通过消息调用当然是串行的了。
    我刚做过试验,证实了我的说法。
    FTS没做实验,有待证实,现在较忙,过两天再做这个实验吧。FTS其实是聚合了一个FTS接口,那篇英文中有例子。
    有兴趣试的话清讲结果告诉我,省我的事了。
    很高兴就这个话题展开讨论,大家共同学习提高。
      

  17.   

    你说的是FTM吧,这个技术比较复杂,我不知道怎么弄?
    有谁能告诉我
      

  18.   

    事实证明我错了,我用以前写的线程例子做测试,没注意以前加的同步操作,让我以为com在不同sta要同步。今天作了实验,重写了com,vb,vc,asp证实com的并发操作没问题。查资料后证明调用CoCreateInstance是创建了新的实例,推翻了我原先单实例的说法。现在反而对sta的同步操作边的概念模糊了。希望共同探讨。
    另,在asp中调用com的sleep并没有影响到其他的请求。证明不同的asp线程式并发执行的。yangmajituipo() 同志再看看你的代码,被跟我犯同样的毛病。
    做过例子后对 acptvc(微软全球技术中心 VC技术支持) 提供的英文变得非常不理解。既然asp线程并发没问题,干吗还弄出个中立线程模型?
    另另,ftm在创建atl object时有选项,没试验,应该不难。期待问题有个圆满的答案。
      

  19.   

    可能各位并没有完全看懂我给的文章。ASP中使用COM对多用户并发性的支持如何?回答这个问题取决于你在ASP中是如何使用COM对象的。在这篇文章的开始部分,作者给出了三种情况:page scope, session scope, application scope。
    只有在session scope 和application scope使用的COM对象才需要讨论它的并发行--换句话说,只有session scope 和application scope使用的COM对象才需要跟其他线程share instance。fftongzhi(程序员也爱家)的代码实际上只是在page scope中使用COM,每次用户请求这个ASP 叶面都会创建一个新的COM instance,没必要讨论并发性的问题。接下来作者谈了ASP中的线程池,都是STA的。最后作者才谈了ASP中的STA线程池去创建session scope和server scope的COM对象是为什么会引起thread affinity问题,以及引入FTM避免这类问题。如果你按照这个思路来看这篇文章的话,你会有所收获的。:-)- 微软全球技术中心 VC技术支持 本贴子以“现状”提供且没有任何担保,同时也没有授予任何权利。具体事项可参见使用条款 
    (http://support.microsoft.com/directory/worldwide/zh-cn/community/terms_chs.asp)。 
    为了为您创建更好的讨论环境,请参加我们的用户满意度调查 
    (http://support.microsoft.com/directory/worldwide/zh-cn/community/survey.asp?key=(S,49854782))。
      

  20.   

    可能大家没有按我的说明进行试验,我说的就是在page scope中使用COM,每次用户请求这个ASP 叶面都会创建一个新的COM instance,但是如果我在该页面内执行该COM的一个费时的方法时,另一个访问该ASP页面的用户(新起IE)
    就会等待,也没有同时创建实例,大家可跟踪DLLGetClassObject,可以看出来。完全不是并发。fftongzhi(程序员也爱家)的做法和我不一样,请大家注意!按我前面的说明100%回再现。
    这是一个非常严重的问题,为什么?
      

  21.   

    简而言之,就是我没有将组件放在会话或应用程序变量中。
    为了大家清楚一点,整理一下操作步骤。
    1、生成带有Sleep(10000)方法的ATL组件
    2、配置在COM+中,
    3、写一个ASP<% set objTest = Server.CreateObject(...) 
                   objTest.
                %>4、启动多个IE同时访问该ASP

    现象再现,
    this is end时间非常紧迫,
    本人热切希望 acptvc(微软全球技术中心 VC技术支持) 
    能够提供帮助,或者由谁能将我的问题广为传播,得到答案后告诉我,
    在此谢谢大家了
      

  22.   

    谢谢acptvc(微软全球技术中心 VC技术支持),昨天仔细研究了com的线程模型
    有所理解,线程同步的问题只存在于不同线程间共用同一个com实例的情况,如在一个线程中创建com,然后在另一个线程访问它,这时com相当于一个临界资源,存在同步控制问题。明白了这一点,所有的线程模型都可以理解了,所以问题全部清楚了。
    用asp中的application,和session保存com,再在其他的页面中访问它,就是这种情况。而在一个单独的asp中创建的com,只要不在其他页面之间传递就不存在同步控制的问题。
    现在有一个问题不太清楚。就是在windows线程之间传递一个com对象决不能简简单单的传递一个指针就完了,涉及到县城环境间的切换。传递windows kernal对象是可以用对象的handle,那传递一个com对象用什么技术呢?
      

  23.   

    现在的问题是并发而不是同步,请大家继续讨论
    现在的问题是并发而不是同步,请大家继续讨论
    现在的问题是并发而不是同步,请大家继续讨论简而言之,就是我没有将组件放在会话或应用程序变量中。
    为了大家清楚一点,整理一下操作步骤。
    1、生成带有Sleep(10000)方法的ATL组件
    2、配置在COM+中,
    3、写一个ASP<% set objTest = Server.CreateObject(...) 
                   objTest.
                %>4、启动多个IE同时访问该ASP

    现象再现,
    this is end时间非常紧迫,
    本人热切希望 acptvc(微软全球技术中心 VC技术支持) 
    能够提供帮助,或者由谁能将我的问题广为传播,得到答案后告诉我,
    在此谢谢大家了
      

  24.   

    yangmajituipo() 我与你的做法一样,也是page scope 创建com
    没有你说的问题,我做了配置com+和没配置两种,都未出现调用被同步的情况
    我的asp
    server端用vbscript client端用javascript
    Mymtscom.mtstest.1没配com+环境
    Mymtscom.testmts.1配了
    同样找你的方法测试,没问题呀
    <%@ Language=VBScript %>
    <%
    dim outstr1 
    dim outstr2 
    dim mtstest
    dim testmts
    set mtstest=server.CreateObject("Mymtscom.mtstest.1")
    set testmts=server.CreateObject("Mymtscom.testmts.1")
    if(request("submit1")<>"")then outstr1=mtstest.sleep(3000)
    if(request("submit2")<>"")then outstr2=testmts.sleep(5000)
    %>
    <HTML>
    <HEAD>
    <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
    <SCRIPT ID=clientEventHandlersJS LANGUAGE=javascript>
    <!--function submit1_onclick() {
    form1.submit()
    return true
    }//-->
    </SCRIPT>
    </HEAD>
    <BODY>
    <%=outstr1%><br>
    <%=outstr2%><br>
    <form name=form1 action=''>
    <br><INPUT id=submit1 type=submit value=Submit1 name=submit1 LANGUAGE=javascript onclick="return submit1_onclick()">
    <br><INPUT id=submit2 type=submit value=Submit2 name=submit2 LANGUAGE=javascript onclick="return submit1_onclick()">
    </form>
    </BODY>
    </HTML>
      

  25.   

    你也可以不用Sleep,就像我前面说的,用GetTickCount得到该方法运行时间,然后用该Time作文件名(避免在文件重名等待)打印启动时间,执行一个费时的操作,打映结束时间,可以发现多个现程运行时,仍然是串行的。(启动时间均在上一方法执行完后,大家可以实验)
    绝对不是并发的,已经得到很多人的共识。
      

  26.   

    补充一下,
    只要大家满足以下条件,就一定能看到结果。1、按我前面历次所讲的作
    2、保证COM+
    3、设置组件可调
    4、Sleep时间够长,或写文件
    5、一定要多个用户几乎同时访问,你可以在自己机器上其多个IE,别人机器上也起多个,一阵点。如果在调试状态下,你可以很清楚地发现确是串行。
    不调试写文件也能看出。所有这些都不管你设的线程模型,是ATL还是标准写法。
    当然,不在ASP下,一点问题都没有,不管客户端如何调,即使同一客户端起多个线程调COM都没关系。
      

  27.   

    大家不要怕麻烦,须知这个问题的存在将会使很多人陷入困局,难道真的不能得到解决吗。to fftongzhi(程序员也爱家)
    继续呀,尽管你的部分想法不太正确,也许你是本着研究的目的,但我却是要实实在在解决这个问题。哎,惨啊
      

  28.   

    到www.myvc.net 或www.easthot.net去看看,有你要的答案
      

  29.   

    to killcat(纱耄) 
    谢谢,我看看
      

  30.   

    to yangmajituipo() 
    你的这个帖子打击了很多朋友的积极性你也可以不用Sleep,就像我前面说的,用GetTickCount得到该方法运行时间,然后用该Time作文件名(避免在文件重名等待)打印启动时间,执行一个费时的操作,打映结束时间,可以发现多个现程运行时,仍然是串行的。(启动时间均在上一方法执行完后,大家可以实验)
    绝对不是并发的,已经得到很多人的共识。特别是最后一句话,可能你现在比较急,所以说出来的话也比较急躁吧!
      

  31.   

    可能有些朋友误会了,我并不是访问不同的ASP页面用同一个组件,
    是在一个页面内执行操作,比如我们有一个页面要花很大的计算量,第一用户的请求到了以后,启动组件,第二个用户的请求到了以后,如果第一个用户还在计算中,就只好等待了,如此一来,就成了串行操作了。!!!一定注意,是同一个ASP页面
      

  32.   

    我也做了一些试验,结论是在ASP调用COM组件确实是非并发的。
    我是按照 yangmajituipo所说的进行了测试,并且打印了一些数据文件,供大家参考。测试环境是两台机器同时运行两个ASP,得出四组数据,写在一个文件中。
    源程序如下:
    STDMETHODIMP CTest::Test()
    { AFX_MANAGE_STATE(AfxGetStaticModuleState()) // TODO: Add your implementation code here
    DWORD dwTime3 = GetTickCount();         //Do something always >10s 
             int i = 0;
             While(i<0x7ffe){
               i++;
               int j = 0;
               While(j<0x7ffe)
                 j++;
             }
    DWORD dwTime4 = GetTickCount(); char cName[50] = "C:\\";
    char cTemp[30] = "";
    sprintf(cTemp,"%d",dwTime4);
    strcat(cName,cTemp);
    strcat(cName,".txt\0");
    ofstream TimeTest(cName,ios::app);
    TimeTest<<"Time Start"<<endl;
    TimeTest<<dwTime3<<endl;
    TimeTest<<"Time end"<<endl;
    TimeTest<<dwTime4<<endl;
    TimeTest<<"Time Count"<<endl;
    TimeTest<<(dwTime4 - dwTime3)<<endl;
    TimeTest.close(); return S_OK;
    }结果发现记录下来的时间没有出现重合的部分,也就是说每个函数的进入时间和结束时间是单独在一段时间区域内的,并没有我们想象的并发的出现。
    希望这些能对大家的讨论有所帮助。
      

  33.   

    已经很长时间没接触ASP了,我把我还记得的一些印象跟你说一下,希望对你所帮助:
    我记得ASP创建对象时,是在DLLHOST.EXE中启动的,如果能够同时存在多个DLLHOST.EXE那就应该可以并发。
    你看看内存里是否有多个DLLHOST.EXE,我觉得应该是没有的,否则太浪费资源了,那么可能是DLLHOST.EXE中的代码导致了这个问题。我现在没有条件试,帮不了你的忙了。不知道IIS中是否有相应的选项呢?
    还有你可以先试一下在一个进程中能不能实现并发调用(至少要利用多线程才行)。
    你给的例子都是在多个独立的进程实现并发调用的。
    唯独在ASP中,只使用了DLLHOST.EXE一个进程进行调用。
    最后,你试一下使用ActiveEXE来编写组件看看能不能独立运行进程。
      

  34.   

    谢谢SnHnBn(大可达) 提供的信息。DllHost是一个代理程序,进程内调用的通过它。在COM+中,配置在同一个COM服务下的组件都在一个DLLHost内运行。不通过ASP时,在一个DllHost内运行的组件调用可以并行,在前面我已作了说明。对单独的一个进程来说,开多个线程调用同一个DllHost内运行的组件也是可以并发的。现在就是不知道为什么ASP不行。伤脑筋啊
      

  35.   

    TO yangmajituipo():
      你说不通过ASP在一个DLLHOST内运行的组件调用可以并行,但是DLLHOST是IIS调用ActiveX用的环境代理程序,其他非Web应用程序并不使用DLLHOST,是不是你理解有误?
      还有,我今天在我的机器上小试了一下,按照我原来的思路,已经解决了你的这个问题,如下:
      在要使用的ASP所在的虚拟目录下设置IIS的应用程序保护级别为中或者高,如果设置为低,表示创建的组件将与IIS公用同一进程,这时候无法实现并发。在保护级别为低的情况下,可以看到在两个浏览器发出请求时,进程中只有一个DLLHOST。如果保护级别为中以上,就会看到有两个DLLHOST,而且并发也可以实现,因为IIS启动了两个代理进程,就如同你使用两个客户端实现的并发操作(因为在两个进程中)。
      从另一个角度来看这个问题,如果想要在一个进程中并发调用多个组件那么
    :1。组件提供的方法本身支持异步调用,但是在你的例子中显然不是异步的。2。该进程创建多个线程进行调用,但是这种方法有太多的困难。我们知道COM+是依赖环境的,基本上我无法想象如何在一个进程中处理这些细节,以我目前所掌握的知识,我觉得非常困难,这一点我希望有着方面的专家进行一下解答。鉴于以上所述,DLLHOST不能并发调用多个组件。
      最后,补充说明一下DLLHOST:在IIS中,为了避免在IIS的进程中直接使用ActiveXDLL带来的安全问题,IIS使用了DLLHOST进行代理。因为如果直接在IIS的进程中直接创建和调用DLL组件,一旦其中一个组件发生异常,整个IIS就会被当掉。而如果使用ActiveXEXE又会导致性能下降。
      在这个问题上,看到很多人都走错了方向,从而陷入了COM原理当中,实质上这是IIS的处理方式,与COM无多大关系。不过使用ActiveEXE时,到是跟线程池有关系,必须保证ActiveEXE能够同时创建多个组件的实例。
      

  36.   

    再强调一点:这个问题出现在同一进程的同步调用上,实质上,在一个进程中不管调用一个还是多个组件的方法,均不能实现并发,除非所调用的方法是异步的,这个问题实质上是一般编程的常识,其实跟COM无关,因为要并发执行,在一个进程中只有创建多个线程才能做到。ActiveDLL是从属于调用进程的。ActiveEXE通过代理与调用进程通讯,但是调用进程仍然不能并发。多个创建/调用进程分别在各自的进程环境中创建/调用ActiveDLL,通过代理共用一个ActiveEXE进程创建多个线程创建/调用各自的ActiveEXE的组件实例(这个过程很复杂)。但是对每一个调用进程,均不能实现并发(除了那个ActiveEXE进程),因此一个DLLHOST.EXE只能同时调用一个方法,它必须等待方法返回。因为DLLHOST.EXE不属于ActiveX,是COM+之外的调用者。  以上观点,纯属个人理解,有不对的地方还请各位多多指点。
      

  37.   

    楼上的已经说到了点子上
    我觉得关键就在于IIS的隔离级别,这决定了是否可以实现同一个页面的并发访问
      

  38.   

    __其他非Web应用程序并不使用DLLHOST
    我认为进程内组件必须通过一个Surrogate,包括WEB程序和DCOM程序。我所描述的现象都是在应用程序的保护级别为中的情况下发生的暂时写到这,希望大家继续补充。