我正在处理一个与外部计算机进行通信的旧应用程序,并且该通信是通过文件进行的。基本上,机器A写入一个文件,B得到它并用另一个文件答复。 当前,一切正常,但是我有一个每5秒调用一次的代码,该代码检查是否存在远程目录(写入文件的位置)。这是代码:
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;
}
似乎上述方法冻结了UI,尤其是当我们使用网络共享时,例如 \\ 10.100.100.1 \ sharedFolder 所以我想在尝试访问之前先对主机进行ping操作
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等待ping结果而不冻结UI?
答案 0 :(得分:2)
因此,您的代码有几处错误:
public static async void PingIP
应该是
public static async Task PingIP
PingIP(address[2], timeout);
应该是
await PingIP(address[2], timeout);
从Task调用同步代码不会使您的代码异步。封装在Task中的同步代码仍然是同步代码。您可以将对同步代码的调用包装在Task.Run
中,以利用线程池,从而从UI线程的角度使它“看起来”是异步的。
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
}
看到上面的代码,您可以看到您还应该使函数DirectoryExists
异步。还有调用DirectoryExists
的代码。等。
从不对Task调用.Result(几乎从不)。这将使您的UI线程再次冻结。 这就是您进行异步编程的方式。一路异步。