Как сделать оболочку с функцией обратного просмотра времени в C #? - PullRequest
0 голосов
/ 12 марта 2019

У меня есть несколько функций с блокировкой вызовов, которые могут зависнуть в случае потери сетевого подключения или других проблем.Я хочу создать универсальную оболочку, позволяющую запускать переданную функцию с указанным тайм-аутом и аргументами.

Прототипы функций:

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: невозможно преобразовать из «группы методов» в «Func»

Я нашел скомпилированный код

var res = ExecuteAsync((args) => Func1(args[0].ToString(), args[1].ToString(), args[2].ToString()), 50, "ip", "user", "pass");

Он слишком тяжелый и нечитаемый.Можно ли это упростить?Как исправить оригинальную ошибку?Может быть, есть другой способ достичь цели?
Я вижу примеры с Action, но мои функции возвращают значение, и у них другой список аргументов.

1 Ответ

1 голос
/ 12 марта 2019

Проблема в том, что у вас есть подпись 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 Framework создает несколькоперегрузки для 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...