c # ping машина в асинхронном режиме - PullRequest
0 голосов
/ 28 июня 2019

Я работаю над унаследованным приложением, которое взаимодействует с внешним компьютером, и связь осуществляется через файл.В основном машина A записывает файл, B получает его и отвечает другим файлом.В настоящее время все работает нормально, но у меня есть код, который вызывается каждые 5 секунд, который проверяет, существует ли удаленный каталог (где записаны файлы) или нет.Tihs - это код:

private delegate bool DirectoryExistsDelegate(string folder);
    public static bool DirectoryExists(string path, int timeout = 2000)
    {
        Func<bool> func = () => Directory.Exists(path);
        Task<bool> task = new Task<bool>(func);
        task.Start();
        return task.Wait(timeout) && task.Result;
    }

Похоже, что приведенный выше метод заморозил пользовательский интерфейс, особенно когда мы используем общий сетевой ресурс, например \\ 10.100.100.1 \ sharedFolder Так что яМысль пинговать хост, прежде чем пытаться получить доступ:

private static IPStatus PingStatus;
    public static async void PingIP(string IPaddress, int timeout = 2000)
    {
        // Verifica indirizzo IP
        if (string.IsNullOrEmpty(IPaddress)) return;
        Ping s = new Ping();
        PingStatus = await s.SendPingAsync(IPaddress, timeout).ContinueWith(pingTask => pingTask.Result.Status);
    }

    private delegate bool DirectoryExistsDelegate(string folder);
    public static bool DirectoryExists(string path, int timeout = 2000)
    {            
        if (path.StartsWith("\\"))
        {
            string[] address = path.Split('\\');
            PingIP(address[2], timeout);

            if (PingStatus != IPStatus.Success) return false;
        }

        Func<bool> func = () => Directory.Exists(path);
        Task<bool> task = new Task<bool>(func);
        task.Start();
        return task.Wait(timeout) && task.Result;
    }

Я называю основной метод следующим образом:

    if (!Uti.DirectoryExists(PathCom.Value, 5000))
        return false;       

Я не знаю, верна ли идея или нет, но логически правильно яУгадай.Проблема в том, что PingStatus всегда возвращает True (при первом вызове), если сервер не существует, так как второй, кажется, работает нормально.Как разрешить SendPingAsync дождаться результата проверки связи и не заморозить интерфейс?

1 Ответ

2 голосов
/ 28 июня 2019

Итак, в вашем коде есть пара ошибок:

Никогда не делать async void, кроме как в обработчике событий:

public static async void PingIP

должно быть

public static async Task PingIP

жду ваших заданий

PingIP(address[2], timeout);

должно быть

await PingIP(address[2], timeout);

Вызов синхронного кода из задачи

Вызов синхронного кода из Задачи не делает ваш код асинхронным. Синхронный код, заключенный в задачу, по-прежнему является синхронным кодом. Вы можете заключить вызовы в синхронный код в Task.Run, чтобы использовать пул потоков, что делает его «асинхронным» с точки зрения потока вашего пользовательского интерфейса.

Func<bool> func = () => Directory.Exists(path);
Task<bool> task = new Task<bool>(func);
task.Start();
return task.Wait(timeout) && task.Result;

Должно быть

bool exists = await Task.Run(() => Directory.Exists(path));

Или для принудительного тайм-аута:

var task = Task.Run(() => Directory.Exists(path));
if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
    // task completed within timeout
} else { 
    // timeout logic
}

Async полностью

Как видно из приведенного выше кода, вы также должны сделать функцию DirectoryExists асинхронной. И код, который вызывает DirectoryExists. и т. д.

Никогда не вызывать .Результат задачи (почти никогда). Это заставит ваш поток пользовательского интерфейса снова зависнуть. Вот как вы делаете асинхронное программирование. Асинхронизация полностью.

...