假设有这个一个COM,以下是他的接口:
public interface udfCOM 
{
string Action1(string[] argv);
void Action2(string[] argv);
void Action3(string[] argv, ref string val1, ref string val2);
}udfCOM允许被创建N个实例,每个实例运行在一个线程里,这些线程可能会并发调用Action1、Action2等函数,Action1、Action2等函数每次运行时间都不长,最多的情况是200毫秒左右。函数Action1、Action2等每次被调用时都会访问同一个资源,而这个资源必须是独占的。这个COM内部已经使用了诸如WaitforSingleObject等方法对任务进行了队列,但可能是因为没处理好,并发线程比较多时还是经常发生多个线程同时抢占资源的情况。现在的情况是这样,我们没有权限去修改这个COM的内部实现,我考虑在ASP.NET中用线程池来替代COM的内部队列。我要同步调用并得到结果,而Action1等函数很多且参数又很复杂,等请问该怎么做?我已经参阅了vs.net 的帮助“ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.2052/cpguide/html/cpconthreadpooling.htm”,感觉我这里需要的回调函数很不好写。附:原来我在web form调用该COM的代码如下,注意,在调用COM之前我可能需要处理我的参数,而且我不希望我处理这些参数的过程也被队列起来:
public class WebForm1 : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
udfCOM com1 = new udfClass();
string cmd = string.Empty;
string result1 = string.Empty;
string result2 = string.Empty; switch(cmd) 
{
case "cmd1":
result2 = Function1();
result1 = com1.Action1(null);
break;
case "cmd2":
com1.Action2(null);
break;
case "cmd3":
result2 = Function1();
com1.Action3(null, ref result1, ref result2);
break;
default:
break;
} this.Response.Write(result1 + "\n<br>\n" + result2);
} private string Function1() 
{
return null;
}
}

解决方案 »

  1.   

    对这方面不熟悉,巨强烈关注中ing...................
      

  2.   

    既然每个COM对象都在独立的线程上,则和COM的同步功能无关
    这里只需要使用.NET提供的线程同步机制既可但问题是既然这里资源访问是互坼的,那为什么还要用多线程?我是说既然这里必须按照顺序访问,那程序为什么不设计为顺序执行的?
      

  3.   

    或许是我没说明白,OK,我们现在不说多线程的问题。
    假设有10个web用户同时请求WebForm1,根据参数的不同有人会调用Action1、有人会调用Action2,他们都要得到运行结果。按理来讲,COM内部应该自己处理好队列的问题,二次开发程序员不用考虑并发的问题,但问题就是他没处理好。所以才需要在WebForm1的代码中对任务(调用COM的某一个有返回值的函数)进行队列,同一个时刻只能有一个人调用COM的某一个函数。
      

  4.   

    也有可能是我对asp.net的运行机制不了解,我不知道多个人并发请求一个web form时IIS是不是开了多个线程处理web form的运行。麻烦知道的仁兄也给解答一下。我想给这个帖子加分,但提示“你最大只能给100分,加上这个分,已经超出范围了”。
      

  5.   

    >>> 按理来讲,COM内部应该自己处理好队列的问题,二次开发程序员不用考虑并发的问题
    COM本身通过STA/MTA/TNA单元可以处理好自身的多线程的问题
    但是对于COM之外的资源,COM组件本身是无法控制多线程访问的问题的。任何组件都是如此>>> 我不知道多个人并发请求一个web form时IIS是不是开了多个线程处理web form的运行
    是如果是这样,那可以设置个全局同步锁,比如在页面的静态构造函数内写:Application["syncroot"] = new object();
    然后:
    lock(Application["syncroot"])
    {
    switch(cmd){...}
    }
      

  6.   

    Application["syncroot"]也可以换成一个类型的静态变量,比如static object syncroot = new object();在这里用这种同步手段可以解决并发的问题,不过这会影响ASP.NET页的性能
    最好还是使用异步的策略,在ASP.NET页内,使用一个新的线程来做这些费时的操作
      

  7.   

    仁兄介绍的这个方法我用过。我说的这个COM组件即udfCOM,在.net中引用之后可以看到两个接口、一个实现类,即IUdfCOM、UdfCOM和udfCOMClass,在.net中调用哪个都是一样的。我曾经专门写了一个类从IUdfCOM这个接口继承,我把它命名为udfCOMClass2,代码如下:public class udfCOMClass2 : udfCOM
    {
    private static udfCOMClass m_udfInstance = new udfCOMClass(); public string Action1(string[] argv)
    {
    string result = string.Empty; lock(m_udfInstance)
    {
    result = m_udfInstance.Action1(argv);
    } return result;
    } public void Action2(string[] argv)
    {
    lock(m_udfInstance)
    {
    m_udfInstance.Action2(argv);
    }
    } public void Action3(string[] argv, ref string val1, ref string val2)
    {
    lock(m_udfInstance)
    {
    m_udfInstance.Action3(argv, ref val1, ref val2);
    }
    }
    }这样用有一个前提,就是假定udfCOMClass访问的资源必须是独占的,这样的代码才有意义。
    事实上我前面也是这么问的。但是实际上udfCOMClass访问的资源有时候可以几个线程并发访问,但是不能太多。udfCOMClass内部也是因为这个问题所以才没有处理好。我之所以想改用线程池或者其他的什么办法,是我以为采用这些办法如果能解决1个的问题,就能解决2个甚至更多的问题。MFC中除了WaitforSingleObject,不是还有WaitForMultipleObjects么,可我就是一时间找不到一个较好的办法来写代码。
      

  8.   

    >>> 但是实际上udfCOMClass访问的资源有时候可以几个线程并发访问,但是不能太多。
    无法理解,嗯
      

  9.   

    我不知道该如何解释,但事实上确实如此。这是一种虚拟资源,如果只有两三个线程并发,udfCOMClass内部能处理得很好,但如果过多就不行了。
      

  10.   

    我们不讨论udfCOMClass了,他的内部实现怎么样不是我现在关心的问题。我们假定它最多允许2个线程并调用它的任何成员函数。现在用“互斥锁”即lock有如下问题:1. lock中的语句,即调用udfCOMClass的成员函数时,可能出现死锁(这是udfCOMClass本身的问题),如果出现了这种情况,本来是只是一个线程塞住了,使用lock后会导致所有线程都阻塞。
    2. lock是互斥的,不能完全满足我限制并发线程的要求,例如我要控制并发数最多为2个。
    3. lock降低了asp.net的性能,并且不能设置超时时间,只能依赖于asp.net的页面超时来提示超时。
      

  11.   

    我花了1夜时间写了一个ashx,从System.Web.IHttpAsyncHandler继承,专门用以调用udfCOMClass2。这个页面使用了自定义的线程池,有超时控制,可以解决楼上的1、3两个问题。但是问题2还是没有得到解决。