为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 C# 中制作一个通用的可超时函数包装器?

如何在 C# 中制作一个通用的可超时函数包装器?

C#
杨__羊羊 2022-10-23 10:06:10
我有一堆阻塞呼叫的功能,在网络连接丢失或其他问题的情况下可能会挂起。我想制作一个通用包装器,允许使用指定的 timout 和参数运行传递的函数。一个函数原型:public static double Func1(string ip, string username, string password);public static int Func2(string ip, string username, string password, string dir);我的包装:    public static T? ExecuteAsync<T>(Func<object[], T> func, int timeout /* sec */, params object[] args) where T : struct    {        var task = Task.Factory.StartNew(() => func(args));        if (task.Wait(timeout * 1000))            return task.Result;        return null;    }预期用途:var res1 = ExecuteAsync<double>(Func1, 30, "1.1.1.1", "user", "looser");var res2 = ExecuteAsync<int>(Func2, 20, "1.1.1.1", "user", "looser", "home");这里的编译器错误(与调用一致ExecuteAsync):错误 CS1503 参数 1:无法从“方法组”转换为“功能”我找到了一个可编译的代码var res = ExecuteAsync((args) => Func1(args[0].ToString(), args[1].ToString(), args[2].ToString()), 50, "ip", "user", "pass");它太重且难以阅读。可以简化吗?如何修复原始错误?也许还有另一种方法可以达到目标?我看到了带有 的示例Action,但是我的函数正在返回一个值,并且它们具有不同的参数列表。
查看完整描述

1 回答

?
狐的传说

TA贡献1804条经验 获得超3个赞

Func1您遇到的问题是具有三个字符串参数的签名,而您的ExecuteAsync方法的第一个参数需要一个以对象数组作为参数的“方法”,即object[]!=string, string, string


public static double Func1(string ip, string username, string password);

Func<object[], T>

您可以拥有的最简单的解决方案是标准化所有“阻塞函数”的签名。在这种情况下,您的情况将如下面的代码所示。你失去了类型安全。Thread班级使用这种方法


static void Main(string[] args) {

    var res1 = ExecuteAsync<double>(Func1, 30, "1.1.1.1", "user", "looser");

}


public static double Func1(object[] args) {

    string ip = (string)args[0], username = (string)args[1], password = (string)args[2];

    // do some work 

    return 0.0;

}


public static T? ExecuteAsync<T>(Func<object[], T> func, int timeout /* sec */, params object[] args) where T : struct {

    var task = Task.Factory.StartNew(() => func(args));

    if (task.Wait(timeout * 1000))

        return task.Result;

    return null;

}

如果您不想失去类型安全性,您可以创建ExecuteAsync方法的多个重载 - 类似于 .NET 框架为 .NET 创建多个重载的方式Func。在这种情况下,您的ExecuteAsync方法将如下所示。您可以为 1、2、4、5 arg 方法创建其他重载,就像Func实现方式一样


public static TRes? ExecuteAsync<T1, T2, T3, TRes>(Func<T1, T2, T3, TRes> func, int timeout /* sec */, T1 arg1, T2 arg2, T3 arg3) where TRes : struct {

    var task = Task.Factory.StartNew(() => func(arg1, arg2, arg3));

    if (task.Wait(timeout * 1000))

        return task.Result;

    return null;

}


查看完整回答
反对 回复 2022-10-23
  • 1 回答
  • 0 关注
  • 124 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信