代码之家  ›  专栏  ›  技术社区  ›  ChrisBD

用参数实现调用泛型函数的超时

  •  1
  • ChrisBD  · 技术社区  · 15 年前

    当第三方COM动态链接库中调用的方法挂起时,我正在尝试使用操作委托类型来强制超时。经过大量的搜索,我发现可以使用Action & lt;& gt;或Func & lt;& gt;并根据调用的方法是否返回参数而传递到4个泛型参数。

    对于这个实例,我希望对返回void并接受2个参数的一系列方法调用超时。下面是我正在组合的代码,但我无法确定如何正确地对beginInvoke进行编码,系统会提示我放置“t arg1”和“t arg2”,但当我输入param1或param2 vs2008时,会告诉我这些值是不确定的。

    以下是目前为止的代码:

    static void CallAndWait(Action<T, T> action, int timeout)
    {
        Thread subThread = null;
        Action<T, T> wrappedAction = (param1, param2) =>
        {
            subThread = Thread.CurrentThread;
            action(param1, param2);
        };
    
        IAsyncResult result = wrappedAction.BeginInvoke(param1, param2, null, null);
        if (((timeout != -1) && !result.IsCompleted) &&
        (!result.AsyncWaitHandle.WaitOne(timeout, false) || !result.IsCompleted))
        {
            if (subThread != null)
            {
                subThread.Abort();
            }
    
            //TODO: close external resource.
    
            throw new TimeoutException();
        }
        else
        {
            action.EndInvoke(result);
        }
    }
    

    如果您能对这里的问题有任何想法,我们将不胜感激。

    下面是根据第一条注释重新编辑的代码

    谢谢你到目前为止的意见。以下是编译的。我似乎无法在调用它时得到正确的语法。

    public static void CallAndWait<T1, T2>(Action<T1, T2> action, int timeout)
    {
        Thread subThread = null;
        T1 param1 = default(T1);
        T2 param2 = default(T2);
    
        Action<T1, T2> wrappedAction = (p1, p2) =>
        {
            subThread = Thread.CurrentThread;
            action(param1, param2);
        };
    
        IAsyncResult result = wrappedAction.BeginInvoke(param1, param2, null, null);
        if (((timeout != -1) && !result.IsCompleted) &&
        (!result.AsyncWaitHandle.WaitOne(timeout, false) || !result.IsCompleted))
        {
            if (subThread != null)
            {
                subThread.Abort();
            }
    
            //TODO: close external resource.
    
            throw new TimeoutException();
        }
        else
        {
            action.EndInvoke(result);
        }
    }
    

    我试图用它调用以下方法来测试它:

    public void LongTimeProcess(int a, string b)
    {
        Thread.Sleep(a);
    }
    

    但以下代码不正确:

        Action<int, string> action = (s1, s2) => LongTimeProcess(s1, s2);
        CallAndWait<int, string>(action(1500, "hello"), 500);
    

    更新代码 我已经发布了代码供论坛用户将来参考。下面的代码似乎有效。 唯一要检查的一点是,当第二次对同一个函数调用例程时,在“action.endinvoke(result)”处,我的单元测试会导致抛出异常,因为结果与该操作没有关联。这可能是因为我的长进程只是一个thread.sleep,在这个例子中,这意味着在我第二次调用时它还没有中止。

        public static void CallAndWait<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2, int timeout)
    
        {
            Thread subThread = null;
            Action<T1, T2> wrappedAction = (p1, p2) =>
            {
                subThread = Thread.CurrentThread;
                action(arg1, arg2);
            };
    
            IAsyncResult result = wrappedAction.BeginInvoke(arg1, arg2, null, null);
            if (((timeout != -1) && !result.IsCompleted) &&
            (!result.AsyncWaitHandle.WaitOne(timeout, false) || !result.IsCompleted))
            {
                if (subThread != null)
                {
                    subThread.Abort();
                }
    
                //TODO: close external resource.
    
                throw new TimeoutException();
            }
            else
            {
                action.EndInvoke(result);
            }
        }
    
    1 回复  |  直到 15 年前
        1
  •  1
  •   Daniel Brückner    15 年前

    一开始应该是

    static void CallAndWait<T>(Action<T, T> action, int timeout)
    

    而不是

    static void CallAndWait(Action<T, T> action, int timeout)
    

    如果参数有不同的类型,甚至是以下类型。

    static void CallAndWait<T1, T2>(Action<T1, T2> action, int timeout)
    

    但我不这么认为。再看一遍。

    更新

    现在我明白你的问题了…当你试图打电话给 CallAndWait() . 呼叫必须是

    CallWithTimeout.CallAndWait(action, 1500, "hello", 500);
    

    而不是你的电话。

    CallWithTimeout.CallAndWait<int, string>(action(1500, "hello"), 500);
    

    所以您必须将方法签名从

    void CallAndWait<T1, T2>(Action<T1, T2> action, int timeout)
    

    void CallAndWait<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2, int timeout)
    

    稍微修改一下身体,就可以了。

    推荐文章