当第三方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);
}
}