我一直试图使一个函数异步运行,以防止窗口冻结每次它ping一个新的地址,但当我试图实现它,VS说,我不能使用等待操作符,因为它的当前状态。有什么建议吗?
public MainWindow()
{
//var reader = new Mp3FileReader(@"ResourcesAudio 2 Connecting.flac");
MediaFoundationReader sound = new MediaFoundationReader(@"ResourcesAudioConnecting.mp3");
var waveOut = new WaveOut(); // or WaveOutEvent()
waveOut.Init(sound);
waveOut.Play();
InitializeComponent();
ContentRendered += (s, e) => { await Connecting(); };
}
private async Task Connecting()
{
AutoResetEvent waiter = new AutoResetEvent(false);
IPAddress ip = IPAddress.Parse("23.185.0.1");
var pingSender = new Ping();
pingSender.PingCompleted += PingCompletedCallback;
pingSender.SendAsync(ip, 1000, waiter);
}
问题是您试图在同步委托中使用await
:
ContentRendered += (s, e) => { await Connecting(); };
要使用await
关键字,您需要定义一个异步委托,然后将其添加到事件中。
这应该可以工作-注意async
关键字允许使用await
关键字:
ContentRendered += async (s, e) => { await Connecting(); };
你还应该等待异步pingSender.SendAsync
方法:
await pingSender.SendAsync(ip, 1000, waiter);
除非您在多个地方使用Connecting
异步方法,否则从可维护性的角度来看,将经典事件处理程序附加到ContentRendered
事件可能是更好的:
ContentRendered += ContentRenderedHandler;
//...
private async void ContentRenderedHandler(object sender, EventArgs e)
{
IPAddress ip = IPAddress.Parse("23.185.0.1");
var pingSender = new Ping();
PingReply pingReply = await pingSender.SendPingAsync(ip, 1000);
// Use the `pingReply` here
}
这与Ermiya Eskandary在他们的回答中所建议的基本相同,唯一的区别是async void
方法上的存在是可见的和显式的。这里使用async void
是正确的,因为该方法是一个事件处理程序。尽管如此,显式是一个好主意,因为async void
方法经常被滥用,导致意外行为,或编译器警告,或两者兼而有之。
更新:您的代码使用了过时的PingCompleted
+SendAsync
方法。Ping
类提供了较新的SendPingAsync
API(。. NET Framework 4.5及更高版本),可以通过async-await直接使用。