我正试图在使用Action委托类型时使用,以便在第三方COM dll中调用的方法挂断时强制超时。经过多次搜索,我发现我可以使用Action<>或者Func<>并传递最多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)”的相同函数上第二次调用例程时抛出异常,因为结果与操作无关。这可能是因为我的LongProcess只是一个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);
}
}
答案 0 :(得分:1)
起初应该是
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)
稍微修改一下身体就应该完成。